1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Elaine Wang <elaine.wang@intel.com>
27 *    Zeng Li <zeng.li@intel.com>
28 *    Edward Lin <edward.lin@intel.com>
29 *
30 */
31
32#include <stdio.h>
33#include <string.h>
34#include "img_types.h"
35#include "psb_def.h"
36#include "psb_drv_debug.h"
37#include "tng_hostheader.h"
38#ifdef _TOPAZHP_PDUMP_
39#include "tng_trace.h"
40#endif
41/* Global stores the latest QP information for the DoHeader()
42 * routine, should be filled in by the rate control algorithm.
43 */
44#define HEADERS_VERBOSE_OUTPUT 0
45
46/* #define USESTATICWHEREPOSSIBLE 1 */
47
48#define MAXNUMBERELEMENTS 16
49
50/* SOME USEFUL TEST FUNCTIONS */
51#ifndef TOPAZ_MTX_HW
52static void Show_Bits(
53    IMG_UINT8 __maybe_unused * ucBitStream,
54    IMG_UINT32 __maybe_unused ByteStartBit,
55    IMG_UINT32 __maybe_unused Bits)
56{
57    return ;
58#if 0
59    char Txt[1024];
60    IMG_UINT32 uiByteSize;
61    IMG_UINT32 uiLp, uiBt, Bcnt;
62    Bcnt = 0;
63    uiByteSize = (Bits + ByteStartBit + 7) >> 3;
64    for (uiLp = 0; uiLp < uiByteSize; uiLp++) {
65        snprintf(Txt, strlen(" "), " ");
66        for (uiBt = 128; uiBt >= 1; uiBt = uiBt >> 1) {
67            Bcnt++;
68            if (Bcnt > Bits + ByteStartBit || Bcnt <= ByteStartBit)
69                snprintf(Txt, sizeof(Txt), "%sX", Txt);
70            else
71                snprintf(Txt, sizeof(Txt), "%s%i", Txt, (ucBitStream[uiLp] & uiBt) > 0);
72        }
73
74        snprintf(Txt, sizeof(Txt), "%s ", Txt);
75        //printf(Txt);
76        if ((uiLp + 1) % 8 == 0) printf("\n");
77    }
78
79    printf("\n\n");
80#endif
81}
82#endif
83
84#ifndef TOPAZ_MTX_HW
85
86static void Show_Elements(
87    MTX_HEADER_PARAMS __maybe_unused * mtx_hdr,
88    MTX_HEADER_ELEMENT __maybe_unused ** aui32ElementPointers)
89{
90    return ;
91#if 0
92    IMG_UINT8 f;
93    IMG_UINT32 TotalByteSize;
94    IMG_UINT32 RTotalByteSize;
95
96    RTotalByteSize = TotalByteSize = 0;
97    for (f = 0; f < mtx_hdr->ui32Elements; f++) {
98#if HEADERS_VERBOSE_OUTPUT
99        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Encoding Element [%i] - Type:%i\n", f, aui32ElementPointers[f]->Element_Type);
100#endif
101        if (aui32ElementPointers[f]->Element_Type == ELEMENT_STARTCODE_RAWDATA ||
102            aui32ElementPointers[f]->Element_Type == ELEMENT_RAWDATA) {
103            TotalByteSize = aui32ElementPointers[f]->ui8Size;
104#if HEADERS_VERBOSE_OUTPUT
105            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Writing %i RAW bits to element.\n", aui32ElementPointers[f]->ui8Size);
106            Show_Bits((IMG_UINT8 *)(&aui32ElementPointers[f]->ui8Size) + 1, 0, TotalByteSize);
107#endif
108            TotalByteSize += 8;
109
110            RTotalByteSize += (((IMG_UINT32)((TotalByteSize + 7) / 8)) * 8);
111            RTotalByteSize += 32;
112        } else {
113            TotalByteSize = 0;
114            switch (aui32ElementPointers[f]->Element_Type) {
115            case ELEMENT_QP:
116#if HEADERS_VERBOSE_OUTPUT
117                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_QP (H264)- for MTX to generate and insert this value\n");
118#endif
119                break;
120            case ELEMENT_SQP:
121#if HEADERS_VERBOSE_OUTPUT
122                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_SQP (H264)- for MTX to generate and insert this value\n");
123#endif
124                break;
125            case ELEMENT_FRAMEQSCALE:
126#if HEADERS_VERBOSE_OUTPUT
127                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_FRAMEQSCALE (H263/MPEG4) - for MTX to generate and insert this value\n");
128#endif
129                break;
130            case ELEMENT_SLICEQSCALE:
131#if HEADERS_VERBOSE_OUTPUT
132                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_SLICEQSCALE (H263/MPEG4) - for MTX to generate and insert this value\n");
133#endif
134                break;
135            case ELEMENT_INSERTBYTEALIGN_H264:
136#if HEADERS_VERBOSE_OUTPUT
137                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_INSERTBYTEALIGN_H264 -  MTX to generate 'rbsp_trailing_bits()' field\n");
138#endif
139                break;
140            case ELEMENT_INSERTBYTEALIGN_MPG4:
141#if HEADERS_VERBOSE_OUTPUT
142                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert token ELEMENT_INSERTBYTEALIGN_MPG4 -  MTX to generate MPEG4 'byte_aligned_bits' field\n");
143#endif
144                break;
145            default:
146                break;
147            }
148
149            RTotalByteSize += 32;
150#if HEADERS_VERBOSE_OUTPUT
151            drv_debug_msg(VIDEO_DEBUG_GENERAL, "No RAW bits\n\n");
152#endif
153        }
154    }
155
156    /* TotalByteSize=TotalByteSize+32+(&aui32ElementPointers[f-1]->Element_Type-&aui32ElementPointers[0]->Element_Type)*8; */
157
158#if HEADERS_VERBOSE_OUTPUT
159    drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nCombined ELEMENTS Stream:\n");
160    Show_Bits((IMG_UINT8 *) mtx_hdr->asElementStream, 0, RTotalByteSize);
161#endif
162#endif //0
163}
164#endif
165
166static void tng_print(unsigned char *ptmp, int num)
167{
168    int tmp;
169    do {
170      for(tmp=0;tmp < num;tmp++) {
171        if(tmp%8==0)
172            drv_debug_msg(VIDEO_DEBUG_GENERAL, "\n\t\t");
173       drv_debug_msg(VIDEO_DEBUG_GENERAL, "\t0x%02x", ptmp[tmp]);
174     }
175     drv_debug_msg(VIDEO_DEBUG_GENERAL, "\n\t\t}\n");
176    } while (0);
177}
178
179/**
180 * Header Writing Functions
181 * Low level bit writing and ue, se functions
182 * HOST CODE
183 */
184static void tng__write_upto8bits_elements(
185    MTX_HEADER_PARAMS *pMTX_Header,
186    MTX_HEADER_ELEMENT **aui32ElementPointers,
187    IMG_UINT8 ui8WriteBits,
188    IMG_UINT16 ui16BitCnt)
189{
190    // This is the core function to write bits/bytes to a header stream, it writes them directly to ELEMENT structures.
191    IMG_UINT8 *pui8WriteBytes;
192    IMG_UINT8 *pui8SizeBits;
193    union {
194        IMG_UINT32 UI16Input;
195        IMG_UINT8 UI8Input[2];
196    } InputVal;
197    IMG_UINT8 ui8OutByteIndex;
198    IMG_INT16 i16Shift;
199    if (ui16BitCnt==0)
200        return ;
201
202//    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: mtx_hdr->ui32Elments overflow (%d)\n", __FUNCTION__, pMTX_Header->ui32Elements);
203    /* WA for klockwork */
204
205//    if (pMTX_Header->ui32Elements >= MAXNUMBERELEMENTS) {
206//        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: mtx_hdr->ui32Elments overflow (%d)\n", __FUNCTION__, pMTX_Header->ui32Elements);
207//        return;
208//    }
209    // First ensure that unused bits  in ui8WriteBits are zeroed
210    ui8WriteBits &= (0x00ff >> (8 - ui16BitCnt));
211    InputVal.UI16Input=0;
212    pui8SizeBits=&(aui32ElementPointers[pMTX_Header->ui32Elements]->ui8Size); //Pointer to the bit count field
213    pui8WriteBytes=&(aui32ElementPointers[pMTX_Header->ui32Elements]->aui8Bits); //Pointer to the space where header bits are to be written
214    ui8OutByteIndex=(pui8SizeBits[0] / 8);
215    if (!(pui8SizeBits[0]&7)) {
216        if (pui8SizeBits[0]>=120) {
217            //Element maximum bits send to element, time to start a new one
218            pMTX_Header->ui32Elements++; // Increment element index
219            aui32ElementPointers[pMTX_Header->ui32Elements]=(MTX_HEADER_ELEMENT *) &pui8WriteBytes[15]; //Element pointer set to position of next element (120/8 = 15 bytes)
220            aui32ElementPointers[pMTX_Header->ui32Elements]->Element_Type=ELEMENT_RAWDATA; //Write ELEMENT_TYPE
221            aui32ElementPointers[pMTX_Header->ui32Elements]->ui8Size=0; // Set new element size (bits) to zero
222            tng__write_upto8bits_elements(pMTX_Header,aui32ElementPointers, ui8WriteBits, ui16BitCnt); // Begin writing to the new element
223        return ;//(IMG_UINT32) ui16BitCnt;
224        }
225        pui8WriteBytes[ui8OutByteIndex]=0; // Beginning a new byte, clear byte
226    }
227    i16Shift=(IMG_INT16) ((8-ui16BitCnt)-(pui8SizeBits[0]&7));
228    if (i16Shift>=0) {
229        ui8WriteBits <<= i16Shift;
230        pui8WriteBytes[ui8OutByteIndex]|=ui8WriteBits;
231        pui8SizeBits[0]=pui8SizeBits[0]+ui16BitCnt;
232    } else {
233        InputVal.UI8Input[1]=(IMG_UINT8) ui8WriteBits+256;
234        InputVal.UI16Input >>= -i16Shift;
235        pui8WriteBytes[ui8OutByteIndex]|=InputVal.UI8Input[1];
236
237        pui8SizeBits[0]=pui8SizeBits[0]+ui16BitCnt;
238        pui8SizeBits[0]=pui8SizeBits[0]-((IMG_UINT8) -i16Shift);
239        InputVal.UI8Input[0]=InputVal.UI8Input[0] >> (8+i16Shift);
240        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, InputVal.UI8Input[0],(IMG_UINT16) -i16Shift);
241    }
242    return ;//(IMG_UINT32) ui16BitCnt;
243}
244
245static void tng__write_upto32bits_elements(
246    MTX_HEADER_PARAMS *pMTX_Header,
247    MTX_HEADER_ELEMENT **aui32ElementPointers,
248    IMG_UINT32 ui32WriteBits,
249    IMG_UINT32 ui32BitCnt)
250{
251    IMG_UINT32 ui32BitLp;
252    IMG_UINT32 ui32EndByte;
253    IMG_UINT8 ui8Bytes[4];
254    drv_debug_msg(VIDEO_DEBUG_GENERAL, "WBS(32) bits %x, cnt = %d\n", ui32WriteBits, ui32BitCnt);
255    for (ui32BitLp=0; ui32BitLp<4; ui32BitLp++) {
256        ui8Bytes[ui32BitLp]=(IMG_UINT8) (ui32WriteBits & 255);
257        ui32WriteBits = ui32WriteBits >> 8;
258    }
259
260    ui32EndByte=((ui32BitCnt+7)/8);
261    if ((ui32BitCnt)%8)
262        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ui8Bytes[ui32EndByte-1], (IMG_UINT8) ((ui32BitCnt)%8));
263    else
264        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ui8Bytes[ui32EndByte-1], 8);
265    if (ui32EndByte>1)
266        for (ui32BitLp=ui32EndByte-1; ui32BitLp>0; ui32BitLp--) {
267            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ui8Bytes[ui32BitLp-1], 8);
268        }
269    return ;//ui32BitCnt;
270}
271
272static void tng__generate_ue(
273    MTX_HEADER_PARAMS *pMTX_Header,
274    MTX_HEADER_ELEMENT **aui32ElementPointers,
275    IMG_UINT32 uiVal)
276{
277    IMG_UINT32 uiLp;
278    IMG_UINT8 ucZeros;
279    IMG_UINT32 uiChunk;
280
281    for (uiLp=1, ucZeros=0;  (uiLp-1) < uiVal ; uiLp=uiLp+uiLp, ucZeros++)
282        uiVal=uiVal-uiLp;
283    // ucZeros = number of preceding zeros required
284    // uiVal = value to append after zeros and 1 bit
285    //** Write preceding zeros
286    for (uiLp=(IMG_UINT32) ucZeros; uiLp+1>8; uiLp-=8)
287        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
288    //** Write zeros and 1 bit set
289    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8) 1, (IMG_UINT8) (uiLp+1));
290    //** Write Numeric part
291    while (ucZeros>8) {
292        ucZeros-=8;
293        uiChunk=(uiVal >> ucZeros);
294        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8) uiChunk, 8);
295        uiVal=uiVal-(uiChunk << ucZeros);
296    }
297    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8) uiVal, ucZeros);
298
299    return ;//ui32BitCnter;
300}
301
302static void tng__generate_se(
303    MTX_HEADER_PARAMS *pMTX_Header,
304    MTX_HEADER_ELEMENT **aui32ElementPointers,
305    int iVal)
306{
307    IMG_UINT32 uiCodeNum;
308
309    if (iVal > 0)
310        uiCodeNum=(IMG_UINT32) (iVal+iVal-1);
311    else
312        uiCodeNum=(IMG_UINT32) (-iVal-iVal);
313    tng__generate_ue(pMTX_Header, aui32ElementPointers, uiCodeNum);
314    return ;//ui32BitCnter;
315}
316
317
318static void tng__insert_element_token(
319    MTX_HEADER_PARAMS *pMTX_Header,
320    MTX_HEADER_ELEMENT **aui32ElementPointers,
321    HEADER_ELEMENT_TYPE ui32Token)
322{
323    IMG_UINT8 ui8Offset = 0;
324    IMG_UINT8 *ui8P = NULL;
325
326    /* WA for klockwork */
327    if ((pMTX_Header->ui32Elements != ELEMENTS_EMPTY) &&
328        (pMTX_Header->ui32Elements >= MAXNUMBERELEMENTS)) {
329        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: mtx_hdr->ui32Elments overflow\n", __FUNCTION__);
330        return;
331    }
332
333
334    if (pMTX_Header->ui32Elements!=ELEMENTS_EMPTY) {
335        if (aui32ElementPointers[pMTX_Header->ui32Elements]->Element_Type==ELEMENT_STARTCODE_RAWDATA ||
336            aui32ElementPointers[pMTX_Header->ui32Elements]->Element_Type==ELEMENT_RAWDATA ||
337            aui32ElementPointers[pMTX_Header->ui32Elements]->Element_Type==ELEMENT_STARTCODE_MIDHDR) {
338            //Add a new element aligned to word boundary
339            //Find RAWBit size in bytes (rounded to word boundary))
340            ui8Offset=aui32ElementPointers[pMTX_Header->ui32Elements]->ui8Size+8+31; // NumberofRawbits (excluding size of bit count field)+ size of the bitcount field
341            ui8Offset/=32; //Now contains rawbits size in words
342            ui8Offset+=1; //Now contains rawbits+element_type size in words
343            ui8Offset*=4; //Convert to number of bytes (total size of structure in bytes, aligned to word boundary).
344        } else {
345            ui8Offset=4;
346        }
347        pMTX_Header->ui32Elements++;
348        ui8P=(IMG_UINT8 *) aui32ElementPointers[pMTX_Header->ui32Elements-1];
349        ui8P+=ui8Offset;
350        aui32ElementPointers[pMTX_Header->ui32Elements]=(MTX_HEADER_ELEMENT *) ui8P;
351    }
352    else
353        pMTX_Header->ui32Elements=0;
354
355    aui32ElementPointers[pMTX_Header->ui32Elements]->Element_Type=ui32Token;
356    aui32ElementPointers[pMTX_Header->ui32Elements]->ui8Size=0;
357}
358
359/*
360 * Intermediary functions to build H264 headers
361 */
362static void tng__H264_writebits_startcode_prefix_element(
363    MTX_HEADER_PARAMS *pMTX_Header,
364    MTX_HEADER_ELEMENT **aui32ElementPointers,
365    IMG_UINT32 ui32ByteSize)
366{
367    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
368    IMG_UINT32 ui32Lp;
369    // Byte aligned (bit 0)
370    //(3 bytes in slice header when slice is first in a picture without sequence/picture_header before picture
371
372    for (ui32Lp=0;ui32Lp<ui32ByteSize-1;ui32Lp++)
373        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
374    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 8);
375    // Byte aligned (bit 32 or 24)
376    return;
377}
378
379// helper function to start new raw data block
380static IMG_BOOL bStartNextRawDataElement = IMG_FALSE;
381static void CheckStartRawDataElement(MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers)
382{
383    if(bStartNextRawDataElement)
384    {
385        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
386        bStartNextRawDataElement = IMG_FALSE;
387    }
388}
389
390
391static void tng__insert_prefix_nal_header(MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers,
392        H264_SLICE_HEADER_PARAMS *pSlHParams, IMG_BOOL __maybe_unused bCabacEnabled)
393{
394    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
395
396    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, pSlHParams->ui8Start_Code_Prefix_Size_Bytes); //Can be 3 or 4 bytes - always 4 bytes in our implementations
397    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
398
399    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,        0, 1);   // forbidden_zero_bit
400
401    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REFERENCE); //MTX fills this value in
402    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
403
404    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 14, 5);    // nal unit type
405
406    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // SVC extension flag
407
408    // nal_unit_header_mvc_extension()
409    {
410        if (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) {
411            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // non_idr_flag flag
412        } else {
413            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    1, 1);   // non_idr_flag flag
414        }
415
416        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 6);   // priority_id flag
417        tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers,    0, 10);   // view_id flag
418
419        //tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 3);   // temporal_id flag
420        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_TEMPORAL_ID); // temporal_id flag
421
422        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_ANCHOR_PIC_FLAG); // anchor_pic_flag
423
424        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
425
426        if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE) {
427            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // interview flag
428        } else {
429            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    1, 1);   // interview flag
430        }
431
432        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    1, 1);   // reserved one bit
433    }
434
435}
436
437static void tng__H264_writebits_VUI_params(
438    MTX_HEADER_PARAMS *pMTX_Header,
439    MTX_HEADER_ELEMENT **aui32ElementPointers,
440    H264_VUI_PARAMS *VUIParams)
441{
442	// Builds VUI Params for the Sequence Header (only present in the 1st sequence of stream)
443	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
444	(0 << 4) |	// aspect_ratio_info_present_flag = 0 in Topaz
445	(0 << 3) |	// overscan_info_present_flag (1 bit) = 0 in Topaz
446	(0 << 2) |	// video_signal_type_present_flag (1 bit) = 0 in Topaz
447	(0 << 1) |	// chroma_loc_info_present_flag (1 bit) = 0 in Topaz
448	(1),												// timing_info_present_flag (1 bit) = 1 in Topaz
449	5);
450	// num_units_in_tick (32 bits) = 1 in Topaz
451        tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->num_units_in_tick, 32);
452
453	// time_scale (32 bits) = frame rate
454	tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->Time_Scale, 32);
455	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// fixed_frame_rate_flag (1 bit) = 1 in Topaz
456	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// nal_hrd_parameters_present_flag (1 bit) = 1 in Topaz
457	//** Definitions for nal_hrd_parameters() contained in VUI structure for Topaz
458	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// cpb_cnt_minus1 ue(v) = 0 in Topaz = 1b
459	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 4);	// bit_rate_scale (4 bits) = 0 in Topaz
460	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 2, 4);	// cpb_size_scale (4 bits) = 2 in Topaz
461
462	tng__generate_ue(pMTX_Header, aui32ElementPointers, VUIParams->bit_rate_value_minus1); // bit_rate_value_minus1[0] ue(v) = (Bitrate/64)-1 [RANGE:0 to (2^32)-2]
463	tng__generate_ue(pMTX_Header, aui32ElementPointers, VUIParams->cbp_size_value_minus1); // cpb_size_value_minus1[0] ue(v) = (CPB_Bits_Size/16)-1   where CPB_Bits_Size = 1.5 * Bitrate  [RANGE:0 to (2^32)-2]
464	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->CBR,1);// cbr_flag[0] (1 bit) = 0 for VBR, 1 for CBR
465	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->initial_cpb_removal_delay_length_minus1, 5); // initial_cpb_removal_delay_length_minus1 (5 bits) = ???
466	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->cpb_removal_delay_length_minus1, 5); // cpb_removal_delay_length_minus1 (5 bits) = ???
467	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->dpb_output_delay_length_minus1, 5); // dpb_output_delay_length_minus1 (5 bits) = ???
468	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, VUIParams->time_offset_length, 5); // time_offst_length (5 bits) = ???
469	///** End of nal_hrd_parameters()
470	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);	// vcl_hrd_parameters_present_flag (1 bit) = 0 in Topaz
471	//if( nal_hrd_parameters_present_flag  ||  vcl_hrd_parameters_present_flag )
472	//FIX for BRN23039
473	//	low_delay_hrd_flag
474	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);	// low_delay_hrd_flag
475
476	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);	// pic_struct_present_flag (1 bit) = 0 in Topaz
477	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);	// bitstream_restriction_flag (1 bit) = 0 in Topaz
478}
479
480
481static void tng__H264ES_writebits_picture_header(
482    MTX_HEADER_PARAMS *pMTX_Header,
483    MTX_HEADER_ELEMENT **aui32ElementPointers,
484    H264_PICTURE_HEADER_PARAMS *pPHParams,
485    H264_SCALING_MATRIX_PARAMS __maybe_unused * psScalingMatrix)
486{
487#ifdef _TOPAZHP_TRACE_
488    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: pic_parameter_set_id = %d\n",__FUNCTION__, pPHParams->pic_parameter_set_id);
489    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: seq_parameter_set_id = %d\n",__FUNCTION__, pPHParams->seq_parameter_set_id);
490    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: entropy_coding_mode_flag = %d\n",__FUNCTION__, pPHParams->entropy_coding_mode_flag);
491    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: weighted_pred_flag = %d\n",__FUNCTION__, pPHParams->weighted_pred_flag);
492    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: weighted_bipred_idc = %d\n",__FUNCTION__, pPHParams->weighted_bipred_idc);
493    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: chroma_qp_index_offset = %d\n",__FUNCTION__, pPHParams->chroma_qp_index_offset);
494    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: constrained_intra_pred_flag = %d\n",__FUNCTION__, pPHParams->constrained_intra_pred_flag);
495    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: transform_8x8_mode_flag = %d\n",__FUNCTION__, pPHParams->transform_8x8_mode_flag);
496    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: pic_scaling_matrix_present_flag = %d\n",__FUNCTION__, pPHParams->pic_scaling_matrix_present_flag);
497    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: bUseDefaultScalingList = %d\n",__FUNCTION__, pPHParams->bUseDefaultScalingList);
498    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: second_chroma_qp_index_offset = %d\n",__FUNCTION__, pPHParams->second_chroma_qp_index_offset);
499#endif
500    //**-- Begin building the picture header element
501    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
502    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, 4);
503
504    ///* GENERATES THE FIRST (STATIC) ELEMENT OF THE H264_PICTURE_HEADER() STRUCTURE *///
505    ///**** ELEMENT BITCOUNT: 18
506
507    // 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
508    // Byte aligned (bit 32)
509    tng__write_upto8bits_elements(pMTX_Header,
510                                  aui32ElementPointers,
511                                  (0 << 7) |    // forbidden_zero_bit
512                                  (3 << 5) |    // nal_ref_idc (2 bits) = 0x3
513                                  (8),  // nal_unit_tpye (5 bits) = 8
514                                  8);
515   // Byte aligned (bit 40)
516    tng__generate_ue(pMTX_Header, aui32ElementPointers, pPHParams->pic_parameter_set_id);  // pic_parameter_set_id ue(v)
517    tng__generate_ue(pMTX_Header, aui32ElementPointers, pPHParams->seq_parameter_set_id);  // seq_parameter_set_id ue(v)
518    tng__write_upto8bits_elements(pMTX_Header,
519                                  aui32ElementPointers,
520                                  (pPHParams->entropy_coding_mode_flag << 4) |    // entropy_coding_mode_flag (1 bit) 0 for CAVLC
521                                  (0 << 3) |                                                                      // pic_order_present_flag (1 bit) = 0
522                                  (1 << 2) |                                                                      // num_slice_group_minus1 ue(v) = 0 in Topaz
523                                  (1 << 1) |                                                                      // num_ref_idx_l0_active_minus1 ue(v) = 0 in Topaz
524                                  (1),                                                                                    // num_ref_idx_l1_active_minus1 ue(v) = 0 in Topaz
525                                  5);
526    // WEIGHTED PREDICTION
527    tng__write_upto8bits_elements(pMTX_Header,
528        aui32ElementPointers,
529        (pPHParams->weighted_pred_flag << 2) |  // weighted_pred_flag (1 bit)
530        (pPHParams->weighted_bipred_idc),           // weighted_bipred_flag (2 bits)
531        3);
532
533    //MTX fills this value in
534    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_QP);
535    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
536
537    ///**** GENERATES THE SECOND ELEMENT OF THE H264_PICTURE_HEADER() STRUCTURE ****///
538    ///**** ELEMENT BITCOUNT: 5
539    //The following field will be generated as a special case by MTX - so not here
540    // tng__generate_se(pMTX_Header, pPHParams->pic_init_qp_minus26); // pic_int_qp_minus26 se(v) = -26 to 25 in Topaz
541    // pic_int_qs_minus26 se(v) = 0 in Topaz
542    tng__generate_se(pMTX_Header, aui32ElementPointers, 0);
543
544    // chroma_qp_index_offset se(v) = 0 in Topaz
545    tng__generate_se(pMTX_Header, aui32ElementPointers, pPHParams->chroma_qp_index_offset);
546
547    // deblocking_filter_control_present_flag (1 bit) = 1 in Topaz
548    // constrained_intra_pred_Flag (1 bit) = 0 in Topaz
549    // redundant_pic_cnt_present_flag (1 bit) = 0 in Topaz
550    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (1 << 2) |
551                                  (pPHParams->constrained_intra_pred_flag << 1) |
552                                  (0),
553                                  3);
554
555    if (pPHParams->transform_8x8_mode_flag ||
556        (pPHParams->second_chroma_qp_index_offset != pPHParams->chroma_qp_index_offset) ||
557        pPHParams->pic_scaling_matrix_present_flag) {
558        // 8x8 transform flag
559        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pPHParams->transform_8x8_mode_flag, 1);
560        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
561        // second_chroma_qp_index_offset se(v) = 0 in Topaz
562        tng__generate_se(pMTX_Header, aui32ElementPointers, pPHParams->second_chroma_qp_index_offset);
563    }
564
565    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_H264); // Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
566    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n",__FUNCTION__);
567
568    return;
569}
570
571static void tng__H264ES_writebits_scalinglists(
572    MTX_HEADER_PARAMS *pMTX_Header,
573    MTX_HEADER_ELEMENT **aui32ElementPointers,
574    H264_SCALING_MATRIX_PARAMS * psScalingMatrix,
575    IMG_BOOL bWrite8x8)
576{
577	// Used by H264_WriteBits_SequenceHeader and H264_WriteBits_PictureHeader
578	IMG_UINT32	ui32List, ui32Index;
579	IMG_INT32	i32CurScale, i32DeltaScale;
580
581	if (!psScalingMatrix)
582	{
583		tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_CUSTOM_QUANT);
584		return;
585	}
586
587	for (ui32List = 0; ui32List < 6; ui32List++)
588	{
589		if (psScalingMatrix->ui32ListMask & (1 << ui32List))
590		{
591			tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); 	// seq_scaling_list_present_flag[ui32List] = 1
592
593			i32CurScale = 8;
594			for (ui32Index = 0; ui32Index < 16; ui32Index++)
595			{
596				i32DeltaScale = ((IMG_INT32)psScalingMatrix->ui8ScalingLists4x4[ui32List][ui32Index]) - i32CurScale;
597				i32CurScale += i32DeltaScale;
598				tng__generate_se(pMTX_Header, aui32ElementPointers, i32DeltaScale); 	// delta_scale
599			}
600		}
601		else
602		{
603			tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); 	// seq_scaling_list_present_flag[ui32List] = 0
604		}
605	}
606
607	if (!bWrite8x8) return;
608
609	for (; ui32List < 8; ui32List++)
610	{
611		if (psScalingMatrix->ui32ListMask & (1 << ui32List))
612		{
613			tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); 	// seq_scaling_list_present_flag[ui32List] = 1
614
615			i32CurScale = 8;
616			for (ui32Index = 0; ui32Index < 64; ui32Index++)
617			{
618				i32DeltaScale = ((IMG_INT32)psScalingMatrix->ui8ScalingLists8x8[ui32List - 6][ui32Index]) - i32CurScale;
619				i32CurScale += i32DeltaScale;
620				tng__generate_se(pMTX_Header, aui32ElementPointers, i32DeltaScale);		// delta_scale
621			}
622		}
623		else
624		{
625			tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); 	// seq_scaling_list_present_flag[ui32List] = 0
626		}
627	}
628
629}
630
631static void tng__H264ES_writebits_sequence_header(
632    MTX_HEADER_PARAMS *pMTX_Header,
633    MTX_HEADER_ELEMENT **aui32ElementPointers,
634    H264_SEQUENCE_HEADER_PARAMS *pSHParams,
635    H264_CROP_PARAMS *psCrop,
636    H264_SCALING_MATRIX_PARAMS * psScalingMatrix,
637    IMG_BOOL8 __maybe_unused bASO)
638{
639    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
640    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, 4);
641
642
643    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
644    // 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
645    // Byte aligned (bit 32)
646    tng__write_upto8bits_elements(pMTX_Header,
647        aui32ElementPointers,(0 << 7) | // forbidden_zero_bit=0
648	(0x3 << 5) | // nal_ref_idc=0x3
649	(7), // nal_unit_type=00111
650        8);
651    // Byte aligned (bit 40)
652    switch (pSHParams->ucProfile) {
653        case SH_PROFILE_BP:
654	    // profile_idc = 8 bits = 66 for BP (PROFILE_IDC_BP)
655            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 66, 8);
656
657            // Byte	aligned	(bit 48)
658            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
659                (1 << 7) |    // constraint_set0_flag = 1 for BP constraints
660                (0 << 6) |    // constraint_set1_flag = 0 for MP constraints
661                (0 << 5) |    // constraint_set2_flag = 0 for EP constraints
662                ((pSHParams->ucLevel==SH_LEVEL_1B ? 1:0) << 4),  // constraint_set3_flag = 1 for level 1b, 0 for others
663                // reserved_zero_4bits = 0
664                8);
665            break;
666        case SH_PROFILE_MP:
667            // profile_idc = 8 bits = 77 for MP (PROFILE_IDC_MP)
668            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 77, 8);
669
670            // Byte aligned (bit 48)
671            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
672                (0 << 7) | // constraint_set0_flag = 0 for no BP constraints
673                (1 << 6) | // constraint_set1_flag = 1 for MP constraints
674                (0 << 5) | // constraint_set2_flag = 0 for EP constraints
675                ((pSHParams->ucLevel==SH_LEVEL_1B ? 1:0) << 4),    // constraint_set3_flag = 1 for level 1b, 0 for others
676                // reserved_zero_4bits = 0
677                8);
678            break;
679        case SH_PROFILE_HP:
680            // profile_idc = 8 bits = 100 for HP (PROFILE_IDC_HP)
681            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 100, 8);
682            // Byte aligned (bit 48)
683            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
684                (0 << 7) | // constraint_set0_flag = 0 for no BP constraints
685                (0 << 6) | // constraint_set1_flag = 0 for no MP constraints
686                (0 << 5) | // constraint_set2_flag = 0 for no EP constraints
687                (0 << 4),  // constraint_set3_flag = 0
688                // reserved_zero_4bits = 0
689                8);
690            break;
691        case SH_PROFILE_H444P:
692            // profile_idc = 8 bits = 244 for H444P (PROFILE_IDC_H444P)
693            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 244, 8);
694
695            // Byte aligned (bit 48)
696            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
697                (0 << 7) |      // constraint_set0_flag = 0 for no BP constraints
698                (0 << 6) |      // constraint_set1_flag = 0 for no MP constraints
699                (0 << 5) |      // constraint_set2_flag = 0 for no EP constraints
700                (0 << 4),	        // constraint_set3_flag = 0
701                // reserved_zero_4bits = 0
702                8);
703            break;
704	}
705
706
707    // Byte aligned (bit 56)
708    // level_idc (8 bits) = 11 for 1b, 10xlevel for others
709    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (pSHParams->ucLevel == SH_LEVEL_1B) ? 11 : (IMG_UINT8)pSHParams->ucLevel, 8);
710    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);		// seq_parameter_set_id = 0
711
712    if ((pSHParams->ucProfile == SH_PROFILE_HP) || (pSHParams->ucProfile == SH_PROFILE_H444P)) {
713        tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);    // chroma_format_idc = 1
714        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);    // bit_depth_luma_minus8 = 0
715        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);    // bit_depth_chroma_minus8 = 0
716        // qpprime_y_zero_transform_bypass_flag = 1 if lossless
717        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSHParams->bIsLossless?1:0, 1);
718        if (pSHParams->bUseDefaultScalingList || pSHParams->seq_scaling_matrix_present_flag) {
719            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); 	// seq_scaling_matrix_present_flag
720            if (!pSHParams->bUseDefaultScalingList) {
721                tng__H264ES_writebits_scalinglists(pMTX_Header, aui32ElementPointers, psScalingMatrix, IMG_TRUE);
722                tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
723            } else {
724                // seq_scaling_list_present_flag[i] = 0; 0 < i < 8
725                tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
726            }
727        } else {
728            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);  // seq_scaling_matrix_present_flag
729        }
730    }
731
732    tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);  // log2_max_frame_num_minus4 = 1
733    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);  // pic_order_cnt_type = 0
734    // log2_max_pic_order_cnt_Isb_minus4 = 2
735    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->log2_max_pic_order_cnt - 4);
736    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->max_num_ref_frames); //num_ref_frames ue(2), typically 2
737    // Bytes aligned (bit 72)
738    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
739        (pSHParams->gaps_in_frame_num_value), // gaps_in_frame_num_value_allowed_Flag	- (1 bit)
740        1);
741    ///**** GENERATES THE SECOND, VARIABLE LENGTH, ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
742    ///**** ELEMENT BITCOUNT: xx
743    //pic_width_in_mbs_minus1: ue(v) from 10 to 44 (176 to 720 pixel per row)
744    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->ucWidth_in_mbs_minus1);
745    //pic_height_in_maps_units_minus1: ue(v) Value from 8 to 35 (144 to 576 pixels per column)
746    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->ucHeight_in_maps_units_minus1);
747    // We don't know the alignment at this point, so will have to use bit writing functions
748    // frame_mb_only_flag 1=frame encoding, 0=field encoding
749    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,pSHParams->ucFrame_mbs_only_flag,1);
750    if (!pSHParams->ucFrame_mbs_only_flag) // in the case of interlaced encoding
751        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,0,1); // mb_adaptive_frame_field_flag = 0 in Topaz(field encoding at the sequence level)
752
753    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,1,1); // direct_8x8_inference_flag=1 in Topaz
754    if (psCrop->bClip) {
755        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,1,1);
756        tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16LeftCropOffset);
757	tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16RightCropOffset);
758	tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16TopCropOffset);
759	tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16BottomCropOffset);
760    } else {
761        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,0,1);
762    }
763
764    ///**** GENERATES THE THIRD ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
765    ///**** ELEMENT BITCOUNT: xx
766    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
767        (pSHParams->VUI_Params_Present), // vui_parameters_present_flag (VUI only in 1st sequence of stream)
768        1);
769
770    if (pSHParams->VUI_Params_Present > 0)
771        tng__H264_writebits_VUI_params(pMTX_Header, aui32ElementPointers, &(pSHParams->VUI_Params));
772
773
774    // Finally we need to align to the next byte
775    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_H264);
776    // Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
777
778    //tng_print(pMTX_Header, 64);
779    return;
780}
781
782
783static void tng__H264ES_writebits_slice_header(
784    MTX_HEADER_PARAMS *pMTX_Header,
785    MTX_HEADER_ELEMENT **aui32ElementPointers,
786    H264_SLICE_HEADER_PARAMS *pSlHParams,
787    IMG_BOOL bCabacEnabled
788)
789{
790    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
791    //Can be 3 or 4 bytes - always 4 bytes in our implementations
792    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, pSlHParams->ui8Start_Code_Prefix_Size_Bytes);
793
794    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
795    ///**** ELEMENT BITCOUNT: 8
796
797    // StartCodePrefix Pregenerated in: Build_H264_4Byte_StartCodePrefix_Element() (4 or 3 bytes)
798    //(3 bytes when slice is first in a picture without sequence/picture_header before picture
799    // Byte aligned (bit 32 or 24)
800    // NOTE: Slice_Type and Frame_Type are always the same, hence SliceFrame_Type
801    tng__write_upto8bits_elements(pMTX_Header,
802                                  aui32ElementPointers, (0 << 7) |                // forbidden_zero_bit
803                                  ((pSlHParams->bReferencePicture) << 5) |        // nal_ref_idc (2 bits)
804                                  ((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE ? 5 : 1)),    // nal_unit_tpye (5 bits) = I-frame IDR, and 1 for  rest
805                                  8);
806
807    //MTX fills this value in
808    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_CURRMBNR);
809    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
810
811    ///**** GENERATES THE SECOND ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
812    /* The following is slice parameter set in BP/MP */
813    //tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32) pSlHParams->First_MB_Address);                               //first_mb_in_slice = First MB address in slice: ue(Range 0 -  1619)
814    tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32)((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) ? SLHP_I_SLICEFRAME_TYPE : pSlHParams->SliceFrame_Type));                                    //slice_type ue(v): 0 for P-slice, 1 for B-slice, 2 for I-slice
815    // kab: //not clean change from IDR to intra, IDR should have separate flag
816    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
817                                  (1 << 5) |                                                                                                                                             //pic_parameter_set_id, ue(v) = 0  (=1b) in Topaz
818                                  pSlHParams->Frame_Num_DO,                                                                                                               //frame_num (5 bits) = frame nuo. in decoding order
819                                  6);
820
821    // interlaced encoding
822    if (pSlHParams->bPiCInterlace) {
823        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);                                          // field_pic_flag = 1
824        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->bFieldType, 1); // bottom_field_flag (0=top field, 1=bottom field)
825    }
826
827    if (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE)
828        tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->Idr_Pic_Id);    // idr_pic_id ue(v)
829
830    if (pSlHParams->bPiCInterlace)
831        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (pSlHParams->Picture_Num_DO + pSlHParams->bFieldType), pSlHParams->log2_max_pic_order_cnt);                    // pic_order_cnt_lsb (6 bits) - picture no in display order
832    else
833        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->Picture_Num_DO, pSlHParams->log2_max_pic_order_cnt);                       // pic_order_cnt_lsb (6 bits) - picture no in display order
834
835
836    if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE)
837        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->direct_spatial_mv_pred_flag, 1);// direct_spatial_mv_pred_flag (1 bit)
838    if (pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE || pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE) {
839        if (pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE && pSlHParams->num_ref_idx_l0_active_minus1 > 0) { //Do we have more then one reference picture?
840            //Override amount of ref pics to be only 1 in L0 direction
841            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
842            tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->num_ref_idx_l0_active_minus1);
843        } else
844            // num_ref_idx_active_override_flag (1 bit) = 0 in Topaz
845            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
846    }
847    if (pSlHParams->SliceFrame_Type != SLHP_I_SLICEFRAME_TYPE && pSlHParams->SliceFrame_Type != SLHP_IDR_SLICEFRAME_TYPE) {
848        if ((pSlHParams->diff_ref_pic_num[0] || pSlHParams->bRefIsLongTermRef[0])
849            || ((pSlHParams->diff_ref_pic_num[1] || pSlHParams->bRefIsLongTermRef[1]) && (pSlHParams->num_ref_idx_l0_active_minus1 > 0))) {
850            //Specifiy first ref pic in L0
851            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); //ref_pic_list_modification_flag_l0
852
853            if (pSlHParams->bRefIsLongTermRef[0]) {
854                tng__generate_ue(pMTX_Header, aui32ElementPointers, 2); // mod_of_pic_num = 2 (long term ref)
855                tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->uRefLongTermRefNum[0]); // long_term_pic_num
856            } else if (pSlHParams->diff_ref_pic_num[0] == 0) {
857                // Can't use 0, so use MaxPicNum which will wrap to 0
858                tng__generate_ue(pMTX_Header, aui32ElementPointers, 1); // mod_of_pic_num = 1 (add to)
859                tng__generate_ue(pMTX_Header, aui32ElementPointers, 31); // abs_diff_minus_1
860            } else if (pSlHParams->diff_ref_pic_num[0] < 0) {
861                tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // mod_of_pic_num = 0 (subtract from)
862                tng__generate_ue(pMTX_Header, aui32ElementPointers, -pSlHParams->diff_ref_pic_num[0] - 1); // abs_diff_minus_1
863            } else {
864                tng__generate_ue(pMTX_Header, aui32ElementPointers, 1); // mod_of_pic_num = 1 (add too)
865                tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->diff_ref_pic_num[0] - 1); // abs_diff_minus_1
866            }
867
868            if ((pSlHParams->diff_ref_pic_num[1] || pSlHParams->bRefIsLongTermRef[1]) && pSlHParams->SliceFrame_Type != SLHP_B_SLICEFRAME_TYPE) { //potentially second reference picture on P
869                if (pSlHParams->bRefIsLongTermRef[1]) {
870                    tng__generate_ue(pMTX_Header, aui32ElementPointers, 2); // mod_of_pic_num = 2 (long term ref)
871                    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->uRefLongTermRefNum[1]); // long_term_pic_num
872                } else if (pSlHParams->diff_ref_pic_num[1] < 0) {
873                    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // mod_of_pic_num = 0 (subtract from)
874                    tng__generate_ue(pMTX_Header, aui32ElementPointers, -pSlHParams->diff_ref_pic_num[1] - 1); // abs_diff_minus_1
875                } else {
876                    tng__generate_ue(pMTX_Header, aui32ElementPointers, 1); // mod_of_pic_num = 1 (add too)
877                    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->diff_ref_pic_num[1] - 1); // abs_diff_minus_1
878                }
879            }
880
881            tng__generate_ue(pMTX_Header, aui32ElementPointers, 3); // mod_of_pic_num = 3 (no more changes)
882        } else
883            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); // ref_pic_list_ordering_flag_I0 (1 bit) = 0, no reference picture ordering in Topaz
884    }
885    if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE) {
886        if (pSlHParams->diff_ref_pic_num[1] || pSlHParams->bRefIsLongTermRef[1]) {
887            //Specifiy first ref pic in L1
888            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); //ref_pic_list_modification_flag_l1
889
890            if (pSlHParams->bRefIsLongTermRef[1]) {
891                tng__generate_ue(pMTX_Header, aui32ElementPointers, 2); // mod_of_pic_num = 2 (long term ref)
892                tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->uRefLongTermRefNum[1]); // long_term_pic_num
893            } else if (pSlHParams->diff_ref_pic_num[1] < 0) {
894                tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // mod_of_pic_num = 0 (subtract from)
895                tng__generate_ue(pMTX_Header, aui32ElementPointers, -pSlHParams->diff_ref_pic_num[1] - 1); // abs_diff_minus_1
896            } else {
897                tng__generate_ue(pMTX_Header, aui32ElementPointers, 1); // mod_of_pic_num = 1 (add too)
898                tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->diff_ref_pic_num[1] - 1); // abs_diff_minus_1
899            }
900
901            tng__generate_ue(pMTX_Header, aui32ElementPointers, 3); // mod_of_pic_num = 3 (no more changes)
902        } else
903            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); // ref_pic_list_ordering_flag_I1 (1 bit) = 0, no reference picture ordering in Topaz
904    }
905    if (pSlHParams->weighted_pred_flag &&
906        ((pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE) || (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE))
907        && (pSlHParams->weighted_bipred_idc == 1)) {
908        int i;
909        tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->luma_log2_weight_denom);
910        tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->chroma_log2_weight_denom); // Always do chroma
911        for (i = 0; i < (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE ? 2 : (pSlHParams->num_ref_idx_l0_active_minus1 + 1)); i++) { // Either 1 or 2
912            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->luma_weight_l0_flag[i], 1);
913            if (pSlHParams->luma_weight_l0_flag[i]) {
914                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->luma_weight_l0[i]);
915                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->luma_offset_l0[i]);
916            }
917            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->chroma_weight_l0_flag[i], 1);
918            if (pSlHParams->chroma_weight_l0_flag[i]) {
919                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->chromaB_weight_l0[i]);
920                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->chromaB_offset_l0[i]);
921                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->chromaR_weight_l0[i]);
922                tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->chromaR_offset_l0[i]);
923            }
924        }
925    }
926
927    if (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) {
928        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);                                                                 // no_output_of_prior_pics_flag (1 bit) = 0
929        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSlHParams->bIsLongTermRef ? 1 : 0, 1);  // long_term_reference_flag (1 bit) = 0
930    } else if (pSlHParams->bReferencePicture) {
931        if (pSlHParams->bIsLongTermRef) {
932            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); // adaptive_ref_pic_marking_mode_flag (1 bit) = 0
933
934            // Allow a single long-term reference
935            tng__generate_ue(pMTX_Header, aui32ElementPointers, 4);                                 // memory_management_control_operation
936            tng__generate_ue(pMTX_Header, aui32ElementPointers, 2);                                 // max_long_term_frame_idx_plus1
937
938            // Set current picture as the long-term reference
939            tng__generate_ue(pMTX_Header, aui32ElementPointers, 6);                                 // memory_management_control_operation
940            tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->uLongTermRefNum);                                       // long_term_frame_idx
941
942            // End
943            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);                                 // memory_management_control_operation
944        } else
945            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);         // adaptive_ref_pic_marking_mode_flag (1 bit) = 0
946    }
947
948    if (bCabacEnabled && ((SLHP_P_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type) ||
949                          (SLHP_B_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type))) {
950        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // hard code cabac_init_idc value of 0
951    }
952    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SQP); //MTX fills this value in
953    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
954
955    ///**** GENERATES ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
956    ///**** ELEMENT BITCOUNT: 11
957    // Next field is generated on MTX with a special commnad (not ELEMENT_RAW) - so not defined here
958    //pucHS=tng__generate_se(pucHS, puiBitPos, pSlHParams->Slice_QP_Delta); //slice_qp_delta se(v) = SliceQPy - (pic_init_qp_minus26+26)
959    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->Disable_Deblocking_Filter_Idc); //disable_deblocking_filter_idc ue(v) = 2?
960    if (pSlHParams->Disable_Deblocking_Filter_Idc != 1) {
961        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebAlphaOffsetDiv2); //slice_alpha_c0_offset_div2 se(v) = 0 (1b) in Topaz
962        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebBetaOffsetDiv2); //slice_beta_offset_div2 se(v) = 0 (1b) in Topaz
963    }
964    //num_slice_groups_minus1 ==0 in Topaz, so no slice_group_change_cycle field here
965    // no byte alignment at end of slice headers
966    return ;
967}
968
969
970static void tng__H264_getelements_skip_P_slice(
971    MTX_HEADER_PARAMS *mtx_hdr,
972    H264_SLICE_HEADER_PARAMS *pSlHParams,
973    IMG_UINT32 MB_No_In_Slice,
974    IMG_BOOL bCabacEnabled)
975{
976    /* Skipped P-Slice
977     * Ensure pSlHParams is filled with appropriate parameters for a B-slice
978     * Essential we initialise our header structures before building
979     */
980    MTX_HEADER_ELEMENT *This_Element;
981    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
982    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
983    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
984    aui32ElementPointers[0] = This_Element;
985
986    /* tng__insert_element_token(mtx_hdr, ELEMENT_STARTCOUNTER); */
987    /* Not sure if this will be required in the final spec */
988    tng__H264ES_writebits_slice_header(mtx_hdr, aui32ElementPointers, pSlHParams, bCabacEnabled);
989    tng__generate_ue(mtx_hdr, aui32ElementPointers, MB_No_In_Slice); /* mb_skip_run = mb_no_in_slice */
990
991    /* Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point) */
992    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_H264);
993    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
994}
995
996
997#if 0
998static void tng__H264_getelements_sequence_header(
999    MTX_HEADER_PARAMS *mtx_hdr,
1000    H264_SEQUENCE_HEADER_PARAMS *pSHParams,
1001    H264_CROP_PARAMS *psCropParams)
1002{
1003    /* Builds a sequence, picture and slice header with from the given inputs parameters (start of new frame)
1004     * Essential we initialise our header structures before building
1005     */
1006    MTX_HEADER_ELEMENT *This_Element;
1007    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1008    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
1009    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
1010    aui32ElementPointers[0] = This_Element;
1011
1012    tng__H264ES_writebits_sequence_header(mtx_hdr, aui32ElementPointers, pSHParams, psCropParams, NULL);
1013    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
1014}
1015#endif
1016
1017//static void tng__H264_getelements_picture_header(MTX_HEADER_PARAMS *mtx_hdr)
1018//{
1019///* Builds a sequence, picture and slice header with from the given inputs parameters (start of new frame)
1020//* Essential we initialise our header structures before building
1021//*/
1022//MTX_HEADER_ELEMENT *This_Element;
1023//MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1024//mtx_hdr->Elements=ELEMENTS_EMPTY;
1025//This_Element=(MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
1026//aui32ElementPointers[0]=This_Element;
1027//
1028//tng__H264ES_writebits_picture_header(mtx_hdr, aui32ElementPointers);
1029//mtx_hdr->Elements++; //Has been used as an index, so need to add 1 for a valid element count
1030//}
1031
1032
1033static void tng__H264_getelements_slice_header(
1034    MTX_HEADER_PARAMS *pMTX_Header,
1035    H264_SLICE_HEADER_PARAMS *pSlHParams,
1036    IMG_BOOL bCabacEnabled
1037)
1038{
1039    /* Builds a single slice header from the given parameters (mid frame)
1040     * Essential we initialise our header structures before building
1041     */
1042    MTX_HEADER_ELEMENT *This_Element;
1043    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1044    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
1045    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
1046    aui32ElementPointers[0] = This_Element;
1047
1048    /* Not sure if this will be required in the final spec */
1049    /* tng__insert_element_token(mtx_hdr, ELEMENT_STARTCOUNTER);*/
1050    tng__H264ES_writebits_slice_header(pMTX_Header, aui32ElementPointers, pSlHParams, bCabacEnabled);
1051
1052    pMTX_Header->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
1053}
1054
1055void H263_NOTFORSIMS_WriteBits_VideoPictureHeader(MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers,
1056					   H263_PICTURE_CODING_TYPE PictureCodingType,
1057					   //IMG_UINT8 ui8Q_Scale,
1058					   H263_SOURCE_FORMAT_TYPE SourceFormatType,
1059					   IMG_UINT8 __maybe_unused ui8FrameRate,
1060					   IMG_UINT32 ui32PictureWidth,
1061					   IMG_UINT32 ui32PictureHeight
1062					   )
1063{
1064    IMG_UINT8 UFEP;
1065
1066    // Essential we insert the element before we try to fill it!
1067    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1068
1069    // short_video_start_marker	= 22 Bits	= 0x20 Picture start code
1070    tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, 32, 22);
1071
1072    // temporal_reference		= 8 Bits	= 0-255	Each picture increased by 1
1073    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_TEMPORAL_REFERENCE);
1074    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1075
1076    // marker_bit				= 1 Bit		= 1
1077    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1078
1079    // zero_bit					= 1 Bits	= 0
1080    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1081
1082    // split_screen_indicator	= 1	Bits	= 0	No direct effect on encoding of picture
1083    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1084
1085    // document_camera_indicator= 1	Bits	= 0	No direct effect on encoding of picture
1086    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1087
1088    // full_picture_freeze_release=1 Bits	= 0	No direct effect on encoding of picture
1089    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1090
1091    // source_format				= 3	Bits	= 1-4	See note
1092    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, SourceFormatType, 3);
1093
1094    if (SourceFormatType != 7)
1095    {
1096	// picture_coding_type		= 1 Bit		= 0/1	0 for I-frame and 1 for P-frame
1097	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, PictureCodingType, 1);
1098	// four_reserved_zero_bits	= 4 Bits	= 0
1099	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 4);
1100    }
1101    // the else block is for PLUSPTYPE header insertion.
1102    else
1103    {
1104	static IMG_UINT8 RTYPE = 0;
1105
1106        // if I- Frame set Update Full Extended PTYPE to true
1107	if (PictureCodingType == I_FRAME)
1108	{
1109	    UFEP = 1;
1110	}
1111	else
1112	{
1113	    UFEP = 0;
1114	}
1115
1116        // write UFEP of 3 bits.
1117	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, UFEP, 3);
1118
1119        // if UFEP was present( if it was 1).
1120        // Optional part of PPTYPE.
1121	if (UFEP == 1)
1122	{
1123	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 6, 3);
1124	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1125
1126            /* 10 reserve bits ( Optional support for the encoding). All are OFF(0).
1127               - Optional Unrestricted Motion Vector (UMV)
1128               - Optional Syntax-based Arithmetic Coding (SAC)
1129               - Optional Advanced Prediction (AP) mode
1130               - Optional Advanced INTRA Coding (AIC) mode
1131               - Optional Deblocking Filter (DF) mode
1132               - Optional Slice Structured (SS) mode
1133               - Optional Reference Picture Selection(RPS) mode.
1134               - Optional Independent Segment Decoding (ISD) mode
1135               - Optional Alternative INTER VLC (AIV) mode
1136               - Optional Modified Quantization (MQ) mode
1137            */
1138	    tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, 0, 10); // 10 reserve bits
1139
1140            /* 4 reserve bits
1141               - 1 (ON) to prevent start code emulation.
1142               - 0  Reserved(shall be 0).
1143               - 0  Reserved(shall be 0).
1144               - 0  Reserved(shall be 0).
1145            */
1146	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 8, 4);	// 4 reserve bits
1147	}
1148        // Optional Part of PPTYPE ends.
1149
1150        // Mandatory part of PPTYPE starts.(MPPTYPE)
1151        // picture_coding_type		= 1 Bit		= 0/1	0 for I-frame and 1 for P-frame
1152	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, PictureCodingType, 3 );
1153
1154        /*
1155            - Optional Reference Picture Resampling (RPR) mode ( OFF) : 0
1156            - Optional Reference Picture Resampling (RPR) mode (OFF) : 0
1157         */
1158	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0 , 2);
1159
1160        // Rounding Type (RTYPE) (1 for P Picture, 0 for all other Picture frames.
1161        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, RTYPE, 1);
1162
1163        /* 2 reserve bits
1164           - 0  Reserved(shall be 0).
1165           - 0  Reserved(shall be 0).
1166        */
1167        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 2);
1168
1169        //   - 1 (ON) to prevent start code emulation.
1170        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1 , 1);
1171		// Mandatory part of PTYPE ends.
1172
1173        // CPM immediately follows the PPTYPE part of the header.
1174        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0 ,1);
1175
1176        /* Custom Picture Format (CPFMT) */
1177        /* if UFEP was present and Source Format type was 7(custom format) */
1178	if (UFEP == 1)
1179	{
1180	    IMG_UINT16 ui16PWI,ui16PHI;
1181
1182            // aspect ratio 4 bits value = 0010 (12:11)
1183			//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0x01, 4);
1184            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 2, 4);
1185
1186            // Picture Width Indication 9 bits.
1187			//ui16PictureWidth --;
1188			//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8)(ui16PictureWidth >> 8), 1);
1189			//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8)(ui16PictureWidth & 0xFF), 8);
1190            ui16PWI = (ui32PictureWidth >> 2) - 1;
1191            tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers,ui16PWI, 9);
1192
1193            // Marker bit 1bit = 1 to prevent start code emulation.
1194	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1195
1196            // Picture Height Indication 9 bits.
1197			//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8)(ui16PictureHeigth >> 8), 1);
1198			//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (IMG_UINT8)(ui16PictureHeigth & 0xFF), 8);
1199            ui16PHI = ui32PictureHeight >> 2;
1200            tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers,ui16PHI, 9);
1201            // good up to that point
1202	}
1203    }
1204    // Insert token to tell MTX to insert rate-control value (QScale is sent as an argument in MTX_Send_Elements_To_VLC(&MTX_Header, FrameQScale))
1205    // vop_quant				= 5 Bits	= x	5-bit frame Q_scale from rate control - GENERATED BY MTX
1206    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_FRAMEQSCALE);
1207
1208    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1209
1210    // if it was not PLUSPTYPE i.e for standard format size insert CPM bit here.
1211    if (SourceFormatType != 7)
1212    {
1213        // cpm	= 1 Bit		= 0	No direct effect on encoding of picture
1214        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0 ,1);
1215    }
1216    // pei						= 1 Bit		= 0	No direct effect on encoding of picture
1217    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1218
1219    return;
1220}
1221
1222void MPEG4_NOTFORSIMS_WriteBits_VOPHeader(MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers,
1223							IMG_BOOL	bIsVOP_coded,
1224							SEARCH_RANGE_TYPE sSearch_range,
1225							VOP_CODING_TYPE sVopCodingType)
1226{
1227    // Essential we insert the element before we try to fill it!
1228    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1229    // visual_object_sequence_start_code	= 32 Bits	= 0x1B6
1230    tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, 438, 32);
1231    // vop_coding_type						= 2 Bits	= 0 for I-frame and 1 for P-frame
1232    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, sVopCodingType, 2);
1233
1234    // modulo_time_base
1235    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_MODULO_TIME_BASE);
1236    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1237
1238    // marker_bit							= 1	Bits	= 1
1239    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1240
1241    // vop_time_increment
1242    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_VOP_TIME_INCREMENT);
1243    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1244
1245    // marker_bit							= 1 Bit		= 1
1246    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1247
1248    if (!bIsVOP_coded)
1249    {
1250	// vop_coded						= 1 Bit		= 0 for skipped frame
1251	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1252       	// byte_aligned_bits (skipped pictures are byte aligned)
1253	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_MPG4); // Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
1254	// End of VOP - skipped picture
1255    } else {
1256	// vop_coded						= 1 Bit		= 1 for normal coded frame
1257	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1258	if (sVopCodingType == P_FRAME)
1259	{
1260	    // vop_rounding_type			= 1 Bit		= 0 vop_rounding_type is 0 in Topaz
1261	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1262	}
1263	// intra_dc_vlc_thr					= 3 Bits	= 0 Use intra DC VLC in Topaz
1264	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 3);
1265	// vop_quant				= 5 Bits	= x	5-bit frame Q_scale from rate control - GENERATED BY MTX
1266	//tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, Frame_Q_scale, 5);
1267	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_FRAMEQSCALE);
1268	if (sVopCodingType == P_FRAME)
1269	{
1270	    // vop_fcode_forward			= 3 bits	= 2 for +/-32 and 3 for +/-64 search range
1271	    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1272	    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, sSearch_range, 3);
1273	}
1274    }
1275}
1276/**************************************************************************************************
1277 * * Function:         H263_GeneratePicHdrTemplate
1278 * * Description:      Generates the h.263 picture header template
1279 * *
1280 * ***************************************************************************************************/
1281void tng__H263_notforsims_prepare_video_pictureheader(
1282    MTX_HEADER_PARAMS* pMTX_Header,
1283    H263_PICTURE_CODING_TYPE ePictureCodingType,
1284    H263_SOURCE_FORMAT_TYPE eSourceFormatType,
1285    IMG_UINT8 ui8FrameRate,
1286    IMG_UINT32 ui32PictureWidth,
1287    IMG_UINT32 ui32PictureHeigth )
1288{
1289    // Essential we initialise our header structures before building
1290    MTX_HEADER_ELEMENT *This_Element;
1291    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1292    pMTX_Header->ui32Elements=ELEMENTS_EMPTY;
1293    This_Element=(MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
1294    aui32ElementPointers[0]=This_Element;
1295
1296    H263_NOTFORSIMS_WriteBits_VideoPictureHeader(
1297               pMTX_Header,
1298               aui32ElementPointers,
1299               ePictureCodingType,
1300               eSourceFormatType,
1301               ui8FrameRate,
1302               ui32PictureWidth,
1303               ui32PictureHeigth );
1304
1305    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
1306}
1307
1308/**************************************************************************************************
1309 * * Function:         MPEG4_GeneratePicHdrTemplate
1310 * * Description:      Generates the MPEG4 picture header template
1311 * *
1312 * ***************************************************************************************************/
1313void tng__MPEG4_notforsims_prepare_vop_header(
1314    MTX_HEADER_PARAMS* pMTX_Header,
1315    IMG_BOOL bIsVOP_coded,
1316    SEARCH_RANGE_TYPE eSearch_range,
1317    VOP_CODING_TYPE eVop_Coding_Type)
1318{
1319    //Builds a single MPEG4 VOP (picture) header from the given parameters
1320    //Essential we initialise our header structures before building
1321    MTX_HEADER_ELEMENT *This_Element;
1322    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1323    pMTX_Header->ui32Elements=ELEMENTS_EMPTY;
1324    This_Element=(MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
1325    aui32ElementPointers[0]=This_Element;
1326
1327    //Frame QScale no longer written here as it is inserted by MTX later (add as parameter to MTX_Send_Elements_To_VLC)
1328    MPEG4_NOTFORSIMS_WriteBits_VOPHeader(
1329	pMTX_Header,
1330	aui32ElementPointers,
1331	bIsVOP_coded,
1332	eSearch_range,
1333	eVop_Coding_Type);
1334
1335    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
1336}
1337
1338void H263_NOTFORSIMS_WriteBits_GOBSliceHeader(MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers)
1339{
1340       // Essential we insert the element before we try to fill it!
1341       tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1342    // gob_resync_marker               = 17            = 0x1
1343       tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, 1, 17);
1344
1345       // gob_number                           = 5                     = 0-17  It is gob number in a picture
1346       tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SLICE_NUM); // Insert token to tell MTX to insert gob_number
1347
1348    // gob_frame_id                            = 2                     = 0-3   See note
1349       tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_GOB_FRAME_ID); // Insert token to tell MTX to insert gob_frame_id
1350
1351       tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
1352
1353       // quant_scale                          = 5                     = 1-32  gob (Slice) Q_scale
1354       // tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ui8GOB_Q_Scale, 5);
1355       tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SLICEQSCALE); // Insert token to tell MTX to insert rate-control value (QScale is sent as an argument
1356}
1357
1358
1359
1360static IMG_UINT8 Bits2Code(IMG_UINT32 CodeVal)
1361{
1362    IMG_UINT8 Bits = 32;
1363    if (CodeVal == 0)
1364        return 1;
1365    while (!(CodeVal & 0x80000000)) {
1366        CodeVal <<= 1;
1367        Bits--;
1368    }
1369    return Bits;
1370}
1371
1372/*
1373 * Intermediary functions to build MPEG4 headers
1374 */
1375#define MATCH_TO_ENC
1376
1377
1378static void tng__MPEG4_writebits_sequence_header(
1379    MTX_HEADER_PARAMS *pMTX_Header,
1380    MTX_HEADER_ELEMENT **aui32ElementPointers,
1381    IMG_BOOL bBFrame,
1382    MPEG4_PROFILE_TYPE bProfile,
1383    IMG_UINT8 ui8Profile_and_level_indication,
1384    FIXED_VOP_TIME_TYPE __maybe_unused sFixed_vop_time_increment,
1385    IMG_UINT32 Picture_Width_Pixels,
1386    IMG_UINT32 Picture_Height_Pixels,
1387    VBVPARAMS *sVBVParams, IMG_UINT32 ui32VopTimeResolution) /* Send NULL pointer if there are no VBVParams */
1388{
1389	// Essential we insert the element before we try to fill it!
1390	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1391	// visual_object_sequence_start_code	= 32 Bits	= 0x1B0
1392	tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, 432, 32);
1393	//profile_and_level_indication			= 8 Bits	= SP L0-L3 and SP L4-L5 are supported
1394	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ui8Profile_and_level_indication, 8);
1395
1396	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1397	// visual_object_start_code				= 32 Bits	= 0x1B5
1398	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1399	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1400	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 8);
1401	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 181, 8);
1402	// is_visual_object_identifier			= 1 Bit 	= 0
1403	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1404	// visual_object_type					= 4 Bits	= Video ID = 1
1405	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 4);
1406	// video_signal_type					= 1 Bit		= 1
1407	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1408	// byte_aligned_bits					= 2 Bits	= 01b (byte_aligned_bits is 2-bit stuffing bit field 01)
1409	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 2);
1410
1411	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1412	//video_object_start_code				= 32 Bits	= 0x100 One VO only in a Topaz video stream
1413	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1414	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1415	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 8);
1416	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1417
1418	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1419	// video_object_layer_start_code		= 32 Bits	= 0x120 One VOL only in a Topaz stream
1420	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1421	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);
1422	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 8);
1423	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 32, 8);
1424	// random_accessible_vol				= 1 Bit		= 0 (P-Frame in GOP)
1425	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1426	if (bProfile == SP)
1427	{
1428		// video_object_type_indication			= 8 Bits	= 0x01 for SP
1429		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 8);
1430#ifndef MATCH_TO_ENC
1431		// is_object_layer_identifier			= 1 Bit		= 0 for SP
1432		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1433#else
1434	// to match the encoder
1435		// is_object_layer_identifier			= 1 Bit
1436		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1437		// video_object_layer_verid				= 4 Bits
1438		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 4);
1439        // video_object_layer_priority			= 3 Bits
1440		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 3);  // 0 is reserved...
1441#endif
1442	}
1443	else
1444	{
1445		// video_object_type_indication			= 8 Bits	= 0x11 for ASP
1446		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 3, 8);
1447		// is_object_layer_identifier			= 1 Bit		= 1 for ASP
1448		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1449		// video_object_layer_verid				= 4 Bits	= 5 is for ASP
1450		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 5, 4);
1451        // video_object_layer_priority			= 3 Bits	= 1 (Highest priority)
1452		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 3);
1453	}
1454	// aspect_ratio_info						= 4 Bits	=0x1 (Square pixel)
1455	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 4);
1456#if !defined(MATCH_TO_ENC) || !defined (EXCLUDE_VOL_CONTROL_PARAMS)
1457	// vol_control_parameters					= 1 Bit		= 1 (Always send VOL control parameters)
1458	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1459
1460    // chroma_format							= 2 Bits	= 01b (4:2:0)
1461	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 2);
1462	// low_delay							= 1 Bit			= 0 with B-frame and 1 without B-frame
1463	if (bBFrame)
1464		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1465	else
1466		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1467    // vbv_parameters						= 1 Bit			=0/1
1468	if (sVBVParams)
1469	{
1470		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1471		 //For recording, only send vbv parameters in 1st sequence header. For video phone, it should be sent more often, such as once per sequence
1472		tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->First_half_bit_rate, 15);			// first_half_bit_rate
1473        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// Marker Bit = 1
1474		tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->Latter_half_bit_rate, 15);			// latter_half_bit_rate
1475        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// Marker Bit = 1
1476		tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->First_half_vbv_buffer_size, 15);	// first_half_vbv_buffer_size
1477        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// Marker Bit = 1
1478        tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->Latter_half_vbv_buffer_size, 3);	//  latter_half_vbv_buffer_size
1479        tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->First_half_vbv_occupancy, 11);		//  first_half_vbv_occupancy
1480        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// Marker Bit = 1
1481		tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, sVBVParams->Latter_half_vbv_occupancy, 15);		//  latter_half_vbv_occupancy
1482        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);	// Marker Bit = 1
1483	}
1484	else
1485		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); // No vbv parameters present
1486#else
1487	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1488#endif
1489	// video_object_layer_shape			= 2 Bits		=	00b	Rectangular shape
1490	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 2);
1491	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1492	// vop_time_increment_solution		= 16 Bits
1493	tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, ui32VopTimeResolution, 16);
1494	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1495#ifndef MATCH_TO_ENC
1496	// fixed_vop_rate					= 1 Bits		=	1 Always fixed frame rate
1497	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1498	// fixed_vop_time_increment			= Variable number of bits based on the time increment resolution.
1499	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, Bits2Code(ui32VopTimeResolution));
1500	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1501#else
1502	// fixed_vop_rate					= 1 Bits		=	0
1503	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1504	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1505#endif
1506	// video_object_layer_width			= 13 Bits		Picture width in pixel units
1507	tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, Picture_Width_Pixels, 13);
1508	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1509	// video_object_layer_height		= 13 Bits		Picture height in pixel units
1510	tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, Picture_Height_Pixels, 13);
1511	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);		// Marker Bit = 1
1512	// interlaced						= 1 Bit			= 0 Topaz only encodes progressive frames
1513	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1514	// obmc_disable						= 1 Bit			= 1 No overlapped MC in Topaz
1515	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1516    // sprite_enable					= 1 Bit			= 0 Not use sprite in Topaz
1517	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1518	// not_8_bit						= 1	Bit			= 0	8-bit video in Topaz
1519	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1520	// quant_type						= 1 Bit			= 0 2nd quantization method in Topaz
1521	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1522	if (bProfile==ASP)
1523	{
1524		// quarter_sample				= 1 Bit			= 0 No ?pel MC in Topaz
1525		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1526	}
1527
1528	// complexity_estimation_disable	= 1 Bit			= 1	No complexity estimation in Topaz
1529	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1530#ifndef MATCH_TO_ENC
1531	// resync_marker_disable			= 1 Bit			= 0 Always enable resync marker in Topaz
1532	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1533#else
1534	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
1535#endif
1536    // data_partitioned					= 1 Bit			= 0 No data partitioning in Topaz
1537	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1538    if (bProfile == ASP)
1539	{
1540		// newpred_enable				= 1 Bit			= 0 No newpred mode in SP/ASP
1541		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1542		// reduced_vop_resolution_enable=1 Bit			= 0	No reduced resolution frame in SP/ASP
1543		tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1544    }
1545    // scalability						= 1 Bit			= 0	No scalability in SP/ASP
1546	tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
1547	// byte_aligned_bits
1548   	tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_MPG4); // Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
1549	return;
1550}
1551
1552
1553/* Utility function */
1554/*
1555  IMG_UINT8 Bits2Code(IMG_UINT32 CodeVal)
1556  {
1557  IMG_UINT8 Bits=32;
1558  if(CodeVal==0)
1559  return 1;
1560  while(!(CodeVal & 0x80000000))
1561  {
1562  CodeVal<<=1;
1563  Bits--;
1564  }
1565  return Bits;
1566  }
1567*/
1568
1569/* MPEG 4 VOP (Picture) Header */
1570static void tng__MPEG4_writebits_VOP_header(
1571    MTX_HEADER_PARAMS *mtx_hdr,
1572    MTX_HEADER_ELEMENT **aui32ElementPointers,
1573    IMG_BOOL    bIsVOP_coded,
1574    IMG_UINT8   VOP_time_increment,
1575    SEARCH_RANGE_TYPE sSearch_range,
1576    VOP_CODING_TYPE sVopCodingType,
1577    IMG_UINT32 VopTimeResolution)
1578{
1579    IMG_BOOL bIsSyncPoint;
1580    /* Essential we insert the element before we try to fill it! */
1581    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1582
1583    /* visual_object_sequence_start_code        = 32 Bits       = 0x1B6 */
1584    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 438, 32);
1585
1586    /* vop_coding_type  = 2 Bits = 0 for I-frame and 1 for P-frame */
1587    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, sVopCodingType, 2);
1588    bIsSyncPoint = (VOP_time_increment > 1) && ((VOP_time_increment) % VopTimeResolution == 0);
1589
1590#ifndef MATCH_TO_ENC
1591    /* modulo_time_base = 1 Bit = 0 As at least  1 synchronization point (I-frame) per second in Topaz */
1592    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1593#else
1594
1595    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, bIsSyncPoint  ? 2 : 0 , bIsSyncPoint ? 2 : 1);
1596
1597#endif
1598
1599    /* marker_bit = 1   Bits    = 1      */
1600    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1601
1602#ifndef MATCH_TO_ENC
1603    /* vop_time_increment = Variable bits based on resolution
1604     *  = x Reset to 0 at I-frame and plus fixed_vop_time_increment each frame
1605     */
1606    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, VOP_time_increment, 5);
1607#else
1608    /* will chrash here... */
1609    tng__write_upto8bits_elements(
1610        mtx_hdr, aui32ElementPointers,
1611        (VOP_time_increment) % VopTimeResolution,
1612        Bits2Code(VopTimeResolution - 1));
1613
1614#endif
1615    /* marker_bit = 1 Bit               = 1      */
1616    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1617
1618    if (!bIsVOP_coded) {
1619        /* vop_coded    = 1 Bit         = 0 for skipped frame */
1620        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1621
1622        /* byte_aligned_bits (skipped pictures are byte aligned) */
1623        /* Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
1624         * End of VOP - skipped picture
1625         */
1626        tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_MPG4);
1627    } else {
1628        /* vop_coded = 1 Bit            = 1 for normal coded frame */
1629        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1630
1631        if (sVopCodingType == P_FRAME) {
1632            /* vop_rounding_type = 1 Bit = 0 vop_rounding_type is 0 in Topaz */
1633            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1634        }
1635
1636        /* intra_dc_vlc_thr = 3 Bits = 0 Use intra DC VLC in Topaz */
1637        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 3);
1638
1639        /* vop_quant = 5 Bits   = x     5-bit frame Q_scale from rate control - GENERATED BY MTX */
1640        /* tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, Frame_Q_scale, 5); */
1641        tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_FRAMEQSCALE);
1642
1643        if (sVopCodingType == P_FRAME) {
1644            /* vop_fcode_forward = 3 bits       = 2 for +/-32 and 3 for +/-64 search range  */
1645            tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_RAWDATA);
1646            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, sSearch_range, 3);
1647        }
1648
1649        /*
1650        **** THE FINAL PART OF VOP STRUCTURE CAN'T BE GENERATED HERE
1651        tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_RAWDATA);
1652        video_packet_data ( )                   = 1st  VP that doesn�t have the VP header
1653
1654        while (nextbits_bytealigned ( ) == resync_marker)
1655        {
1656        video_packet _header( )
1657        video_packet _data( )                   All MB in the slice
1658        }
1659        */
1660    }
1661}
1662
1663/*
1664 * Intermediary functions to build H263 headers
1665 */
1666static void H263_writebits_VideoSequenceHeader(
1667    MTX_HEADER_PARAMS *mtx_hdr,
1668    MTX_HEADER_ELEMENT **aui32ElementPointers,
1669    IMG_UINT8 Profile_and_level_indication)
1670{
1671    /* Essential we insert the element before we try to fill it! */
1672    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1673
1674    /* visual_object_sequence_start_code        = 32 Bits       = 0x1B0 */
1675    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 432, 32);
1676
1677    /* profile_and_level_indication = 8 Bits =  x SP L0-L3 and SP L4-L5 are supported */
1678    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, Profile_and_level_indication, 8);
1679
1680    /* visual_object_start_code = 32 Bits       = 0x1B5 */
1681
1682    /* 437 too large for the   tng__write_upto32bits_elements function */
1683    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 437, 32);
1684
1685    /* is_visual_object_identifier = 1 Bit              = 0 */
1686    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1687
1688    /* is_visual_object_type    = 4 Bits        = 1 Video ID */
1689    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 4);
1690
1691    /* video_signal_type = 1 Bit                = 0      */
1692    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1693
1694    /* byte_aligned_bits = 2 Bits = 01b byte_aligned_bits is 2-bit stuffing bit field 01 */
1695    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 2);
1696
1697    /* video_object_start_code  =32 Bits        = 0x100 One VO only in a Topaz video stream */
1698    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 256, 32);
1699
1700    return;
1701}
1702
1703static void H263_writebits_VideoPictureHeader(
1704    MTX_HEADER_PARAMS *mtx_hdr,
1705    MTX_HEADER_ELEMENT **aui32ElementPointers,
1706    IMG_UINT8 Temporal_Ref,
1707    H263_PICTURE_CODING_TYPE PictureCodingType,
1708    //IMG_UINT8 Q_Scale,
1709    H263_SOURCE_FORMAT_TYPE SourceFormatType,
1710    IMG_UINT8 __maybe_unused FrameRate,
1711    IMG_UINT32 PictureWidth,
1712    IMG_UINT32 PictureHeight)
1713{
1714    IMG_UINT8 UFEP;
1715
1716    /* Essential we insert the element before we try to fill it! */
1717    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1718
1719    /* short_video_start_marker = 22 Bits       = 0x20 Picture start code */
1720    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 32, 22);
1721
1722    /* temporal_reference = 8 Bits      = 0-255 Each picture increased by 1 */
1723    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, Temporal_Ref, 8);
1724
1725    /* marker_bit = 1 Bit = 1    */
1726    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1727
1728    /* zero_bit = 1 Bits        = 0      */
1729    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1730
1731    /* split_screen_indicator   = 1     Bits    = 0     No direct effect on encoding of picture */
1732    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1733
1734    /* document_camera_indicator= 1     Bits    = 0     No direct effect on encoding of picture */
1735    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1736
1737    /* full_picture_freeze_release=1 Bits       = 0     No direct effect on encoding of picture */
1738    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1739
1740    /* source_format                            = 3     Bits    = 1-4   See note */
1741    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, SourceFormatType, 3);
1742
1743    if (SourceFormatType != 7) {
1744        // picture_coding_type          = 1 Bit         = 0/1   0 for I-frame and 1 for P-frame
1745        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, PictureCodingType, 1);
1746        // four_reserved_zero_bits      = 4 Bits        = 0
1747        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 4);
1748    } else {
1749        static unsigned char  RTYPE = 0;
1750
1751        // if I- Frame set Update Full Extended PTYPE to true
1752        if (PictureCodingType == I_FRAME) {
1753            UFEP = 1;
1754        } else {
1755            UFEP = 0;
1756        }
1757        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, UFEP, 3);
1758        if (UFEP == 1) {
1759            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 6, 3);
1760            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1761
1762            /* 10 reserve bits ( Optional support for the encoding). All are OFF(0).
1763             *  - Optional Unrestricted Motion Vector (UMV)
1764             *  - Optional Syntax-based Arithmetic Coding (SAC)
1765             *  - Optional Advanced Prediction (AP) mode
1766             *  - Optional Advanced INTRA Coding (AIC) mode
1767             *  - Optional Deblocking Filter (DF) mode
1768             *  - Optional Slice Structured (SS) mode
1769             *  - Optional Reference Picture Selection(RPS) mode.
1770             *  - Optional Independent Segment Decoding (ISD) mode
1771             *  - Optional Alternative INTER VLC (AIV) mode
1772             *  - Optional Modified Quantization (MQ) mode */
1773
1774            tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 0, 10);
1775            // 10 reserve bits
1776            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 8, 4);
1777            // 4 reserve bits
1778        }
1779        // picture_coding_type          = 1 Bit         = 0/1   0 for I-frame and 1 for P-frame
1780        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, PictureCodingType, 3);
1781
1782        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 2);
1783        // two_reserve_bits,      rounding_type,       two_reserve_bits       marker_bit       CPM
1784        // Rounding Type (RTYPE) (1 for P Picture, 0 for all other Picture frames.
1785        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, RTYPE, 1);
1786        //2 reserve bits
1787        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 2);
1788        //   - 1 (ON) to prevent start code emulation.
1789        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1 , 1);
1790        // CPM immediately follows the PPTYPE part of the header.
1791        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0 , 1);
1792
1793
1794        if (UFEP == 1) {
1795            IMG_UINT16 ui16PWI, ui16PHI;
1796            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 4);
1797            // aspect ratio
1798            //PictureWidth--;
1799            //tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)(PictureWidth >> 8), 1);
1800            //tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)(PictureWidth & 0xFF), 8);
1801            //Width = (PWI-1)*4, Height = PHI*4, see H263 spec 5.1.5
1802            ui16PWI = (PictureWidth >> 2) - 1;
1803            tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)ui16PWI, 9);
1804
1805            tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1806            // marker_bit                               = 1 Bit         = 1
1807            //tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)(PictureHeight >> 8), 1);
1808            //tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)(PictureHeight & 0xFF), 8);
1809
1810            ui16PHI = PictureHeight >> 2;
1811            tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, (IMG_UINT8)ui16PHI, 9);
1812            // good up to that point
1813            //  tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 1, 1);
1814            // marker_bit                               = 1 Bit         = 1
1815            // just checking
1816        }
1817    }
1818    // vop_quant                                = 5 Bits        = x     5-bit frame Q_scale from rate control - GENERATED BY MTX
1819    //tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, ui8Q_Scale, 5);
1820    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_FRAMEQSCALE); // Insert token to tell MTX to insert rate-control value (QScale
1821										   //is sent as an argument in MTX_Send_Elements_To_VLC(&MTX_Header, FrameQScale))
1822    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_RAWDATA);
1823    // zero_bit                                 = 1 Bit         = 0
1824    // pei                                              = 1 Bit         = 0     No direct effect on encoding of picture
1825    if (SourceFormatType != 7) {
1826        tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1827    }
1828
1829    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, 0, 1);
1830    // FOLLOWING SECTION CAN'T BE GENERATED HERE
1831    //gob_data( )
1832    //for(i=1; i<num_gob_in_picture; i++) {
1833    //      gob_header( )
1834    //      gob_data( )
1835    // }
1836    return;
1837}
1838
1839static void H263_writebits_GOBSliceHeader(
1840    MTX_HEADER_PARAMS *mtx_hdr,
1841    MTX_HEADER_ELEMENT **aui32ElementPointers,
1842    IMG_UINT8 GOBNumber,
1843    IMG_UINT8 GOBFrameId)
1844{
1845    /* Essential we insert the element before we try to fill it! */
1846    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1847
1848    /* gob_resync_marker                = 17            = 0x1 */
1849    tng__write_upto32bits_elements(mtx_hdr, aui32ElementPointers, 1, 17);
1850
1851    /* gob_number = 5   = 0-17  It is gob number in a picture */
1852    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, GOBNumber, 5);
1853
1854    /* gob_frame_id     = 2 = 0-3       See note */
1855    tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, GOBFrameId, 2);
1856
1857    /* quant_scale      = 5     = 1-32  gob (Slice) Q_scale  */
1858    /* tng__write_upto8bits_elements(mtx_hdr, aui32ElementPointers, GOB_Q_Scale, 5); */
1859
1860    /* Insert token to tell MTX to insert rate-control value
1861     *  (QScale is sent as an argument in MTX_Send_Elements_To_VLC(&MTX_Header, SliceQScale))
1862     */
1863    tng__insert_element_token(mtx_hdr, aui32ElementPointers, ELEMENT_SLICEQSCALE);
1864    return;
1865}
1866
1867/*
1868 * High level functions to call when a H263 header is required - HOST ROUTINES
1869 */
1870//static void tng__H263_getelements_videosequence_header(
1871//MTX_HEADER_PARAMS *mtx_hdr,
1872//IMG_UINT8 Profile_and_level_indication)
1873//{
1874///* Builds a single H263 video sequence header from the given parameters */
1875//
1876///* Essential we initialise our header structures before building */
1877//MTX_HEADER_ELEMENT *This_Element;
1878//MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1879//mtx_hdr->Elements=ELEMENTS_EMPTY;
1880//This_Element=(MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
1881//aui32ElementPointers[0]=This_Element;
1882//
1883//H263_writebits_VideoSequenceHeader(mtx_hdr, aui32ElementPointers, Profile_and_level_indication);
1884//
1885//mtx_hdr->Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
1886//}
1887
1888//static void tng__H263_getelements_videopicture_header(
1889//MTX_HEADER_PARAMS *mtx_hdr,
1890//IMG_UINT8 Temporal_Ref,
1891//H263_PICTURE_CODING_TYPE PictureCodingType,
1892//H263_SOURCE_FORMAT_TYPE SourceFormatType,
1893//IMG_UINT8 FrameRate,
1894//IMG_UINT16 PictureWidth,
1895//IMG_UINT16 PictureHeigth)
1896//{
1897///* Essential we initialise our header structures before building */
1898//MTX_HEADER_ELEMENT *This_Element;
1899//MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1900//mtx_hdr->Elements=ELEMENTS_EMPTY;
1901//This_Element=(MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
1902//aui32ElementPointers[0]=This_Element;
1903//
1904//H263_writebits_VideoPictureHeader(
1905//mtx_hdr, aui32ElementPointers,
1906//Temporal_Ref,
1907//PictureCodingType,
1908//SourceFormatType,
1909//FrameRate,
1910//PictureWidth,
1911//PictureHeigth);
1912//
1913//mtx_hdr->Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
1914//}
1915
1916//static void tng__H263_getelements_GOBslice_header(
1917//MTX_HEADER_PARAMS *mtx_hdr,
1918//IMG_UINT8 GOBNumber,
1919//IMG_UINT8 GOBFrameId)
1920//{
1921///* Essential we initialise our header structures before building */
1922//MTX_HEADER_ELEMENT *This_Element;
1923//MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
1924//mtx_hdr->Elements=ELEMENTS_EMPTY;
1925//This_Element=(MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
1926//aui32ElementPointers[0]=This_Element;
1927//
1928//H263_writebits_GOBSliceHeader(mtx_hdr, aui32ElementPointers, GOBNumber, GOBFrameId);
1929//
1930//mtx_hdr->Elements++; //Has been used as an index, so need to add 1 for a valid element count
1931//}
1932
1933// SEI_INSERTION
1934static void tng__H264ES_writebits_AUD_header(
1935    MTX_HEADER_PARAMS *pMTX_Header,
1936    MTX_HEADER_ELEMENT **aui32ElementPointers)
1937{
1938    // Essential we insert the element before we try to fill it!
1939    tng__insert_element_token(pMTX_Header,
1940        aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1941
1942    tng__H264_writebits_startcode_prefix_element(pMTX_Header,
1943        aui32ElementPointers, 4); // 00 00 00 01 start code prefix
1944
1945    tng__write_upto8bits_elements(pMTX_Header,
1946        aui32ElementPointers, 9, 8); // AUD nal_unit_type = 09
1947
1948    // primary_pic_type  u(3) 0=I slice, 1=P or I slice, 2=P,B or I slice
1949    tng__write_upto8bits_elements(pMTX_Header,
1950        aui32ElementPointers, 2, 3);
1951
1952    tng__write_upto8bits_elements(pMTX_Header,
1953        aui32ElementPointers, 1 << 4, 5); // rbsp_trailing_bits
1954
1955    // Write terminator
1956    tng__write_upto8bits_elements(pMTX_Header,
1957        aui32ElementPointers, 0x80, 8);
1958    return;
1959}
1960
1961//#define SEI_NOT_USE_TOKEN_ALIGN
1962
1963static void tng__H264ES_writebits_SEI_buffering_period_header(
1964    MTX_HEADER_PARAMS *pMTX_Header,
1965    MTX_HEADER_ELEMENT **aui32ElementPointers,
1966    IMG_UINT8 ui8NalHrdBpPresentFlag,
1967    IMG_UINT8 ui8nal_cpb_cnt_minus1,
1968    IMG_UINT8 ui8nal_initial_cpb_removal_delay_length,
1969    IMG_UINT32 __maybe_unused ui32nal_initial_cpb_removal_delay,
1970    IMG_UINT32 __maybe_unused ui32nal_initial_cpb_removal_delay_offset,
1971    IMG_UINT8 ui8VclHrdBpPresentFlag,
1972    IMG_UINT8 ui8vcl_cpb_cnt_minus1,
1973    IMG_UINT32 ui32vcl_initial_cpb_removal_delay,
1974    IMG_UINT32 ui32vcl_initial_cpb_removal_delay_offset)
1975{
1976    IMG_UINT8 ui8SchedSelIdx;
1977    IMG_UINT8 ui8PayloadSizeBits;
1978#ifdef SEI_NOT_USE_TOKEN_ALIGN
1979    IMG_UINT8 ui8Pad;
1980#endif
1981
1982    // Essential we insert the element before we try to fill it!
1983    tng__insert_element_token(pMTX_Header,
1984        aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
1985
1986    tng__H264_writebits_startcode_prefix_element(pMTX_Header,
1987        aui32ElementPointers, 3); // 00 00 01 start code prefix
1988
1989    tng__write_upto8bits_elements(pMTX_Header,
1990        aui32ElementPointers, 6, 8); // nal_unit_type = 06 (SEI Message)
1991
1992    tng__write_upto8bits_elements(pMTX_Header,
1993        aui32ElementPointers, 0, 8); // SEI payload type (buffering period)
1994
1995    ui8PayloadSizeBits = 1; // seq_parameter_set_id bitsize = 1
1996    if (ui8NalHrdBpPresentFlag)
1997        ui8PayloadSizeBits += ((ui8nal_cpb_cnt_minus1 + 1)
1998                               * ui8nal_initial_cpb_removal_delay_length * 2);
1999    if (ui8VclHrdBpPresentFlag)
2000        ui8PayloadSizeBits += ((ui8vcl_cpb_cnt_minus1 + 1)
2001                               * ui8nal_initial_cpb_removal_delay_length * 2);
2002
2003    tng__write_upto8bits_elements(pMTX_Header,
2004                                  aui32ElementPointers,
2005                                  ((ui8PayloadSizeBits + 7) / 8),
2006                                  8);
2007    // SEI payload size = No of bytes required for SEI payload
2008    // (including seq_parameter_set_id)
2009
2010    //seq_parameter_set_id      ue(v) = 0 default? = 1 (binary)
2011    //= sequence parameter set containing HRD attributes
2012    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);
2013
2014    if (ui8NalHrdBpPresentFlag) {
2015        for (ui8SchedSelIdx = 0; ui8SchedSelIdx <= ui8nal_cpb_cnt_minus1; ui8SchedSelIdx++) {
2016            // ui32nal_initial_cpb_removal_delay = delay between time of arrival in CODED PICTURE BUFFER of coded data of this access
2017            // unit and time of removal from CODED PICTURE BUFFER of the coded data of the same access unit.
2018            // Delay is based on the time taken for a 90 kHz clock.
2019            // Range >0 and < 90000 * (CPBsize / BitRate)
2020            // For the 1st buffering period after HARDWARE REFERENCE DECODER initialisation.
2021            // tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_NAL_INIT_CPB_REMOVAL_DELAY); // Eventually use this if firmware value required
2022
2023            //tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers, ui32nal_initial_cpb_removal_delay, ui8nal_initial_cpb_removal_delay_length);
2024            tng__insert_element_token(pMTX_Header,
2025                                      aui32ElementPointers,
2026                                      BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY);
2027
2028            // ui32nal_initial_cpb_removal_delay_offset = used for the SchedSelIdx-th CPB in combination with the cpb_removal_delay to
2029            // specify the initial delivery time of coded access units to the CODED PICTURE BUFFER initial_cpb_removal_delay_offset
2030            // Delay is based on the time taken for a 90 kHz clock.
2031            // NOT USED BY DECODERS and is needed only for the delivery scheduler (HSS) specified in Annex C
2032
2033            tng__insert_element_token(pMTX_Header,
2034                                      aui32ElementPointers,
2035                                      BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY_OFFSET);
2036        }
2037    }
2038    if (ui8VclHrdBpPresentFlag) {
2039        for (ui8SchedSelIdx = 0; ui8SchedSelIdx <= ui8vcl_cpb_cnt_minus1; ui8SchedSelIdx++) {
2040            tng__insert_element_token(pMTX_Header,
2041                                      aui32ElementPointers,
2042                                      ELEMENT_STARTCODE_RAWDATA);
2043            // tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_VCL_INIT_CPB_REMOVAL_DELAY); // Eventually use this if firmware value required
2044            tng__write_upto32bits_elements(pMTX_Header,
2045                                           aui32ElementPointers,
2046                                           ui32vcl_initial_cpb_removal_delay,
2047                                           ui8nal_initial_cpb_removal_delay_length);
2048            // tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_VCL_INIT_CPB_REMOVAL_DELAY_CPB); // Eventually use this if firmware value required
2049            tng__write_upto32bits_elements(pMTX_Header,
2050                                           aui32ElementPointers,
2051                                           ui32vcl_initial_cpb_removal_delay_offset,
2052                                           ui8nal_initial_cpb_removal_delay_length);
2053        }
2054    }
2055
2056    // Pad to end of byte
2057#ifdef SEI_NOT_USE_TOKEN_ALIGN
2058    if (!ui8VclHrdBpPresentFlag)
2059        tng__insert_element_token(pMTX_Header,
2060                                  aui32ElementPointers,
2061                                  ELEMENT_STARTCODE_RAWDATA);
2062    ui8Pad = (ui8PayloadSizeBits + 7) / 8;
2063    ui8Pad = (ui8Pad * 8) - ui8PayloadSizeBits;
2064    if (ui8Pad > 0)
2065        tng__write_upto8bits_elements(pMTX_Header,
2066                                      aui32ElementPointers,
2067                                      1 << (ui8Pad - 1),
2068                                      ui8Pad); // SEI payload type (buffering period)
2069#else
2070    tng__insert_element_token(pMTX_Header,
2071                              aui32ElementPointers,
2072                              ELEMENT_INSERTBYTEALIGN_H264);
2073    // Tell MTX to insert the byte align field
2074    tng__insert_element_token(pMTX_Header,
2075                              aui32ElementPointers,
2076                              ELEMENT_STARTCODE_RAWDATA);
2077#endif
2078
2079    // Write terminator
2080    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0x80, 8);
2081
2082    return;
2083}
2084
2085//#define SEI_HOSTCALC_CPB_DPB
2086
2087static void tng__H264ES_writebits_SEI_picture_timing_header(
2088    MTX_HEADER_PARAMS *pMTX_Header, MTX_HEADER_ELEMENT **aui32ElementPointers,
2089    IMG_UINT8 ui8CpbDpbDelaysPresentFlag,
2090    IMG_UINT32 ui32cpb_removal_delay_length_minus1,
2091    IMG_UINT32 ui32dpb_output_delay_length_minus1,
2092    IMG_UINT32 __maybe_unused ui32cpb_removal_delay,
2093    IMG_UINT32 __maybe_unused ui32dpb_output_delay,
2094    IMG_UINT8 ui8pic_struct_present_flag,
2095    IMG_UINT8 ui8pic_struct,
2096    IMG_UINT8 ui8NumClockTS,
2097    IMG_UINT8 *aui8clock_timestamp_flag,
2098    IMG_UINT8 ui8full_timestamp_flag,
2099    IMG_UINT8 ui8seconds_flag,
2100    IMG_UINT8 ui8minutes_flag,
2101    IMG_UINT8 ui8hours_flag,
2102    IMG_UINT8 ui8seconds_value,
2103    IMG_UINT8 ui8minutes_value,
2104    IMG_UINT8 ui8hours_value,
2105    IMG_UINT8 ui8ct_type,
2106    IMG_UINT8 ui8nuit_field_based_flag,
2107    IMG_UINT8 ui8counting_type,
2108    IMG_UINT8 ui8discontinuity_flag,
2109    IMG_UINT8 ui8cnt_dropped_flag,
2110    IMG_UINT8 ui8n_frames,
2111    IMG_UINT8 ui8time_offset_length,
2112    IMG_INT32 i32time_offset)
2113{
2114    IMG_UINT8 ui8PayloadSizeBits, ui8Tmp;
2115#ifdef SEI_NOT_USE_TOKEN_ALIGN
2116    IMG_UINT8 ui8Pad;
2117#endif
2118
2119    // Essential we insert the element before we try to fill it!
2120    tng__insert_element_token(pMTX_Header,
2121                              aui32ElementPointers,
2122                              ELEMENT_STARTCODE_RAWDATA);
2123
2124    tng__H264_writebits_startcode_prefix_element(pMTX_Header,
2125            aui32ElementPointers,
2126            3); // 00 00 01 start code prefix
2127
2128    tng__write_upto8bits_elements(pMTX_Header,
2129                                  aui32ElementPointers,
2130                                  6, 8); // nal_unit_type = 06 (SEI Message)
2131
2132    tng__write_upto8bits_elements(pMTX_Header,
2133                                  aui32ElementPointers,
2134                                  1, 8); // SEI payload type (picture timing)
2135
2136
2137    // Precalculate the payload bit size
2138    ui8PayloadSizeBits = 0;
2139    if (ui8CpbDpbDelaysPresentFlag)
2140        ui8PayloadSizeBits += ui32cpb_removal_delay_length_minus1
2141                              + 1 + ui32dpb_output_delay_length_minus1 + 1;
2142
2143    if (ui8pic_struct_present_flag) {
2144        ui8PayloadSizeBits += 4;
2145        for (ui8Tmp = 0; ui8Tmp < ui8NumClockTS ; ui8Tmp++) {
2146            ui8PayloadSizeBits += 1;
2147
2148            if (aui8clock_timestamp_flag[ui8Tmp]) {
2149                ui8PayloadSizeBits += 2 + 1 + 5 + 1 + 1 + 1 + 8;
2150                if (ui8full_timestamp_flag)
2151                    ui8PayloadSizeBits += 6 + 6 + 5;
2152                else {
2153                    ui8PayloadSizeBits += 1;
2154                    if (ui8seconds_flag) {
2155                        ui8PayloadSizeBits += 6 + 1;
2156                        if (ui8minutes_flag) {
2157                            ui8PayloadSizeBits += 6 + 1;
2158                            if (ui8hours_flag)
2159                                ui8PayloadSizeBits += 5;
2160                        }
2161                    }
2162                }
2163
2164                if (ui8time_offset_length > 0)
2165                    ui8PayloadSizeBits += ui8time_offset_length;
2166            }
2167        }
2168    }
2169
2170    tng__write_upto8bits_elements(pMTX_Header,
2171                                  aui32ElementPointers,
2172                                  ((ui8PayloadSizeBits + 7) / 8), 8);
2173    // SEI payload size = No of bytes required for SEI payload (including seq_parameter_set_id)
2174
2175
2176    if (ui8CpbDpbDelaysPresentFlag) {
2177        //SEI_INSERTION
2178#ifdef SEI_HOSTCALC_CPB_DPB
2179        tng__write_upto32bits_elements(pMTX_Header,
2180                                       aui32ElementPointers,
2181                                       ui32cpb_removal_delay,
2182                                       ui32cpb_removal_delay_length_minus1 + 1); // cpb_removal_delay
2183        tng__write_upto32bits_elements(pMTX_Header,
2184                                       aui32ElementPointers,
2185                                       ui32dpb_output_delay,
2186                                       ui32dpb_output_delay_length_minus1 + 1); // dpb_output_delay
2187#else
2188        tng__insert_element_token(pMTX_Header,
2189                                  aui32ElementPointers,
2190                                  PTH_SEI_NAL_CPB_REMOVAL_DELAY);
2191        tng__insert_element_token(pMTX_Header,
2192                                  aui32ElementPointers,
2193                                  PTH_SEI_NAL_DPB_OUTPUT_DELAY);
2194#endif
2195    }
2196
2197    if (ui8pic_struct_present_flag) {
2198        tng__insert_element_token(pMTX_Header,
2199                                  aui32ElementPointers,
2200                                  ELEMENT_STARTCODE_RAWDATA);
2201        tng__write_upto8bits_elements(pMTX_Header,
2202                                      aui32ElementPointers,
2203                                      ui8pic_struct, 4); // See TRM able D 1 ?Interpretation of pic_struct
2204
2205        for (ui8Tmp = 0; ui8Tmp < ui8NumClockTS ; ui8Tmp++) {
2206            tng__write_upto8bits_elements(pMTX_Header,
2207                                          aui32ElementPointers,
2208                                          aui8clock_timestamp_flag[ui8Tmp], 1);
2209
2210            if (aui8clock_timestamp_flag[ui8Tmp]) {
2211                tng__write_upto8bits_elements(pMTX_Header,
2212                                              aui32ElementPointers,
2213                                              ui8ct_type, 2);
2214                // (2=Unknown) See TRM Table D 2 ?Mapping of ct_type to source picture scan
2215                tng__write_upto8bits_elements(pMTX_Header,
2216                                              aui32ElementPointers,
2217                                              ui8nuit_field_based_flag, 1);
2218                tng__write_upto8bits_elements(pMTX_Header,
2219                                              aui32ElementPointers,
2220                                              ui8counting_type, 5);
2221                // See TRM Table D 3 ?Definition of counting_type values
2222                tng__write_upto8bits_elements(pMTX_Header,
2223                                              aui32ElementPointers,
2224                                              ui8full_timestamp_flag, 1);
2225                tng__write_upto8bits_elements(pMTX_Header,
2226                                              aui32ElementPointers,
2227                                              ui8discontinuity_flag, 1);
2228                tng__write_upto8bits_elements(pMTX_Header,
2229                                              aui32ElementPointers,
2230                                              ui8cnt_dropped_flag, 1);
2231                tng__write_upto8bits_elements(pMTX_Header,
2232                                              aui32ElementPointers,
2233                                              ui8n_frames, 8);
2234
2235                if (ui8full_timestamp_flag) {
2236                    tng__write_upto8bits_elements(pMTX_Header,
2237                                                  aui32ElementPointers,
2238                                                  ui8seconds_value, 6); // 0 - 59
2239                    tng__write_upto8bits_elements(pMTX_Header,
2240                                                  aui32ElementPointers,
2241                                                  ui8minutes_value, 6); // 0 - 59
2242                    tng__write_upto8bits_elements(pMTX_Header,
2243                                                  aui32ElementPointers,
2244                                                  ui8hours_value, 5); // 0 - 23
2245                } else {
2246                    tng__write_upto8bits_elements(pMTX_Header,
2247                                                  aui32ElementPointers,
2248                                                  ui8seconds_flag, 1);
2249
2250                    if (ui8seconds_flag) {
2251                        tng__write_upto8bits_elements(pMTX_Header,
2252                                                      aui32ElementPointers,
2253                                                      ui8seconds_value, 6); // 0 - 59
2254                        tng__write_upto8bits_elements(pMTX_Header,
2255                                                      aui32ElementPointers,
2256                                                      ui8minutes_flag, 1);
2257
2258                        if (ui8minutes_flag) {
2259                            tng__write_upto8bits_elements(pMTX_Header,
2260                                                          aui32ElementPointers,
2261                                                          ui8minutes_value, 6); // 0 - 59
2262                            tng__write_upto8bits_elements(pMTX_Header,
2263                                                          aui32ElementPointers,
2264                                                          ui8hours_flag, 1);
2265
2266                            if (ui8hours_flag)
2267                                tng__write_upto8bits_elements(pMTX_Header,
2268                                                              aui32ElementPointers,
2269                                                              ui8hours_value, 5); // 0 - 23
2270                        }
2271                    }
2272                }
2273
2274                if (ui8time_offset_length > 0) {
2275                    // Two's complement storage : If time_offset<0 = ((2 ^ v) + time_offset)
2276                    if (i32time_offset < 0)
2277                        tng__write_upto32bits_elements(pMTX_Header,
2278                                                       aui32ElementPointers,
2279                                                       (IMG_UINT32)((2 ^ ui8time_offset_length) + i32time_offset),
2280                                                       ui8time_offset_length);
2281                    else
2282                        tng__write_upto32bits_elements(pMTX_Header,
2283                                                       aui32ElementPointers,
2284                                                       (IMG_UINT32) i32time_offset,
2285                                                       ui8time_offset_length);
2286                }
2287            }
2288        }
2289    }
2290
2291#ifdef SEI_NOT_USE_TOKEN_ALIGN
2292    // Pad to end of byte
2293    if (!ui8pic_struct_present_flag)
2294        tng__insert_element_token(pMTX_Header,
2295                                  aui32ElementPointers,
2296                                  ELEMENT_STARTCODE_RAWDATA);
2297    ui8Pad = (ui8PayloadSizeBits + 7) / 8;
2298    ui8Pad = (ui8Pad * 8) - ui8PayloadSizeBits;
2299    if (ui8Pad > 0)
2300        tng__write_upto8bits_elements(pMTX_Header,
2301                                      aui32ElementPointers,
2302                                      1 << (ui8Pad - 1),
2303                                      ui8Pad); // SEI payload type (buffering period)
2304#else
2305    tng__insert_element_token(pMTX_Header,
2306                              aui32ElementPointers,
2307                              ELEMENT_INSERTBYTEALIGN_H264); // Tell MTX to insert the byte align field
2308    tng__insert_element_token(pMTX_Header,
2309                              aui32ElementPointers,
2310                              ELEMENT_STARTCODE_RAWDATA);
2311#endif
2312
2313    // Write terminator
2314    tng__write_upto8bits_elements(pMTX_Header,
2315                                  aui32ElementPointers,
2316                                  0x80, 8);
2317    return;
2318}
2319
2320
2321
2322void tng__H264ES_prepare_AUD_header(unsigned char *virtual_addr)
2323{
2324    // Essential we initialise our header structures before building
2325    MTX_HEADER_PARAMS * pMTX_Header = (MTX_HEADER_PARAMS *)virtual_addr;
2326    MTX_HEADER_ELEMENT *This_Element;
2327    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2328    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
2329    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
2330    aui32ElementPointers[0] = This_Element;
2331
2332    tng__H264ES_writebits_AUD_header(pMTX_Header, aui32ElementPointers);
2333
2334    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
2335}
2336
2337
2338void tng__H264ES_prepare_SEI_buffering_period_header(
2339    unsigned char *virtual_addr,
2340    IMG_UINT8 ui8nal_cpb_cnt_minus1,
2341    IMG_UINT8 ui8nal_initial_cpb_removal_delay_length,
2342    IMG_UINT8 ui8NalHrdBpPresentFlag,
2343    IMG_UINT32 ui32nal_initial_cpb_removal_delay,
2344    IMG_UINT32 ui32nal_initial_cpb_removal_delay_offset,
2345    IMG_UINT8 ui8VclHrdBpPresentFlag,
2346    IMG_UINT32 ui32vcl_initial_cpb_removal_delay,
2347    IMG_UINT32 ui32vcl_initial_cpb_removal_delay_offset)
2348{
2349    // Essential we initialise our header structures before building
2350    MTX_HEADER_PARAMS * pMTX_Header = (MTX_HEADER_PARAMS *)virtual_addr;
2351    MTX_HEADER_ELEMENT *This_Element;
2352    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2353    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
2354    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
2355    aui32ElementPointers[0] = This_Element;
2356
2357    tng__H264ES_writebits_SEI_buffering_period_header(
2358        pMTX_Header, aui32ElementPointers,
2359        ui8NalHrdBpPresentFlag,
2360        ui8nal_cpb_cnt_minus1,
2361        ui8nal_initial_cpb_removal_delay_length,
2362        ui32nal_initial_cpb_removal_delay,
2363        ui32nal_initial_cpb_removal_delay_offset,
2364        ui8VclHrdBpPresentFlag,
2365        ui8nal_cpb_cnt_minus1,
2366        ui32vcl_initial_cpb_removal_delay,
2367        ui32vcl_initial_cpb_removal_delay_offset);
2368
2369    pMTX_Header->ui32Elements++;
2370    //Has been used as an index, so need to add 1 for a valid element count
2371    return;
2372}
2373
2374void tng__H264ES_prepare_SEI_picture_timing_header(
2375    unsigned char *virtual_addr,
2376    IMG_UINT8 ui8CpbDpbDelaysPresentFlag,
2377    IMG_UINT32 ui32cpb_removal_delay_length_minus1,
2378    IMG_UINT32 ui32dpb_output_delay_length_minus1,
2379    IMG_UINT32 ui32cpb_removal_delay,
2380    IMG_UINT32 ui32dpb_output_delay,
2381    IMG_UINT8 ui8pic_struct_present_flag,
2382    IMG_UINT8 ui8pic_struct,
2383    IMG_UINT8 ui8NumClockTS,
2384    IMG_UINT8 *aui8clock_timestamp_flag,
2385    IMG_UINT8 ui8full_timestamp_flag,
2386    IMG_UINT8 ui8seconds_flag,
2387    IMG_UINT8 ui8minutes_flag,
2388    IMG_UINT8 ui8hours_flag,
2389    IMG_UINT8 ui8seconds_value,
2390    IMG_UINT8 ui8minutes_value,
2391    IMG_UINT8 ui8hours_value,
2392    IMG_UINT8 ui8ct_type,
2393    IMG_UINT8 ui8nuit_field_based_flag,
2394    IMG_UINT8 ui8counting_type,
2395    IMG_UINT8 ui8discontinuity_flag,
2396    IMG_UINT8 ui8cnt_dropped_flag,
2397    IMG_UINT8 ui8n_frames,
2398    IMG_UINT8 ui8time_offset_length,
2399    IMG_INT32 i32time_offset)
2400{
2401    // Essential we initialise our header structures before building
2402    MTX_HEADER_PARAMS * pMTX_Header = (MTX_HEADER_PARAMS *)virtual_addr;
2403    MTX_HEADER_ELEMENT *This_Element;
2404    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2405    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
2406    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
2407    aui32ElementPointers[0] = This_Element;
2408
2409    tng__H264ES_writebits_SEI_picture_timing_header(
2410        pMTX_Header, aui32ElementPointers,
2411        ui8CpbDpbDelaysPresentFlag,
2412        ui32cpb_removal_delay_length_minus1,
2413        ui32dpb_output_delay_length_minus1,
2414        ui32cpb_removal_delay,
2415        ui32dpb_output_delay,
2416        ui8pic_struct_present_flag,
2417        ui8pic_struct,
2418        ui8NumClockTS,
2419        aui8clock_timestamp_flag,
2420        ui8full_timestamp_flag,
2421        ui8seconds_flag,
2422        ui8minutes_flag,
2423        ui8hours_flag,
2424        ui8seconds_value,
2425        ui8minutes_value,
2426        ui8hours_value,
2427        ui8ct_type,
2428        ui8nuit_field_based_flag,
2429        ui8counting_type,
2430        ui8discontinuity_flag,
2431        ui8cnt_dropped_flag,
2432        ui8n_frames,
2433        ui8time_offset_length,
2434        i32time_offset);
2435
2436    pMTX_Header->ui32Elements++;
2437    //Has been used as an index, so need to add 1 for a valid element count
2438    return;
2439}
2440
2441static void tng__H264ES_set_sequence_level_profile(
2442    H264_SEQUENCE_HEADER_PARAMS *pSHParams,
2443    IMG_UINT8 uiLevel,
2444    IMG_UINT8 uiProfile)
2445{
2446    switch (uiLevel) {
2447    case 10:
2448        pSHParams->ucLevel =  SH_LEVEL_10;
2449        break;
2450    case 111:
2451        pSHParams->ucLevel =  SH_LEVEL_1B;
2452        break;
2453    case 11:
2454        pSHParams->ucLevel =  SH_LEVEL_11;
2455        break;
2456    case 12:
2457        pSHParams->ucLevel =  SH_LEVEL_12;
2458        break;
2459    case 20:
2460        pSHParams->ucLevel =  SH_LEVEL_20;
2461        break;
2462    case 30:
2463        pSHParams->ucLevel =  SH_LEVEL_30;
2464        break;
2465    case 31:
2466        pSHParams->ucLevel =  SH_LEVEL_31;
2467        break;
2468    case 32:
2469        pSHParams->ucLevel =  SH_LEVEL_32;
2470        break;
2471    case 40:
2472        pSHParams->ucLevel =  SH_LEVEL_40;
2473        break;
2474    case 41:
2475        pSHParams->ucLevel =  SH_LEVEL_41;
2476        break;
2477    case 42:
2478        pSHParams->ucLevel =  SH_LEVEL_42;
2479        break;
2480    default:
2481        pSHParams->ucLevel =  SH_LEVEL_30;
2482        break;
2483    }
2484
2485    switch (uiProfile) {
2486    case 5:
2487        pSHParams->ucProfile  = SH_PROFILE_BP;
2488        break;
2489    case 6:
2490        pSHParams->ucProfile  = SH_PROFILE_MP;
2491        break;
2492    default:
2493        pSHParams->ucProfile  = SH_PROFILE_MP;
2494        break;
2495    }
2496    return ;
2497}
2498
2499void tng__H264ES_prepare_sequence_header(
2500    void *pHeaderMemory,
2501    H264_VUI_PARAMS *psVUI_Params,
2502    H264_CROP_PARAMS *psCropParams,
2503    IMG_UINT16 ui16PictureWidth,
2504    IMG_UINT16 ui16PictureHeight,
2505    IMG_UINT32 ui32CustomQuantMask,
2506    IMG_UINT8 ui8ProfileIdc,
2507    IMG_UINT8 ui8LevelIdc,
2508    IMG_UINT8 ui8FieldCount,
2509    IMG_UINT8 ui8MaxNumRefFrames,
2510    IMG_BOOL  bPpsScaling,
2511    IMG_BOOL  bUseDefaultScalingList,
2512    IMG_BOOL  bEnableLossless,
2513    IMG_BOOL  bASO
2514)
2515{
2516    /* Builds a sequence, picture and slice header with from the given inputs parameters (start of new frame)
2517     * Essential we initialise our header structures before building
2518     */
2519    H264_SEQUENCE_HEADER_PARAMS SHParams;
2520    /* Route output elements to memory provided */
2521    MTX_HEADER_PARAMS  *mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMemory;
2522    MTX_HEADER_ELEMENT *This_Element;
2523    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2524    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
2525    This_Element = mtx_hdr->asElementStream;
2526    aui32ElementPointers[0] = This_Element;
2527
2528    memset(&SHParams, 0, sizeof(H264_SEQUENCE_HEADER_PARAMS));
2529
2530    SHParams.ucProfile = ui8ProfileIdc - 5;
2531    SHParams.ucLevel = (ui8LevelIdc != 111) ? ui8LevelIdc : SH_LEVEL_1B;
2532    SHParams.ucWidth_in_mbs_minus1 = (IMG_UINT8)((ui16PictureWidth >> 4)- 1);
2533    SHParams.ucHeight_in_maps_units_minus1 = (IMG_UINT8)((ui16PictureHeight >> 4) - 1);
2534    SHParams.gaps_in_frame_num_value = IMG_FALSE;
2535    SHParams.VUI_Params_Present = psVUI_Params->vui_flag;
2536    if (SHParams.VUI_Params_Present)
2537        memcpy(&SHParams.VUI_Params, psVUI_Params, sizeof(H264_VUI_PARAMS));
2538    SHParams.ucFrame_mbs_only_flag = (ui8FieldCount > 1) ? IMG_FALSE : IMG_TRUE;
2539
2540    SHParams.seq_scaling_matrix_present_flag = (bPpsScaling) ? IMG_FALSE : (IMG_UINT8)(ui32CustomQuantMask);
2541    SHParams.bUseDefaultScalingList = (bPpsScaling) ? IMG_FALSE : bUseDefaultScalingList;
2542
2543
2544    SHParams.seq_scaling_matrix_present_flag = (ui32CustomQuantMask != 0 && !bPpsScaling);
2545    SHParams.bUseDefaultScalingList = (bUseDefaultScalingList && !bPpsScaling);
2546
2547    SHParams.max_num_ref_frames = ui8MaxNumRefFrames;
2548    SHParams.bIsLossless = bEnableLossless;
2549    SHParams.log2_max_pic_order_cnt = 6;
2550#ifdef _TOPAZHP_PDUMP_
2551    tng_trace_seq_header_params(&SHParams);
2552#endif
2553    tng__H264ES_writebits_sequence_header(mtx_hdr, aui32ElementPointers, &SHParams, psCropParams, NULL, bASO);
2554    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
2555}
2556
2557static void tng__H264ES_writebits_mvc_sequence_header(
2558    MTX_HEADER_PARAMS *pMTX_Header,
2559    MTX_HEADER_ELEMENT **aui32ElementPointers,
2560    H264_SEQUENCE_HEADER_PARAMS *pSHParams,
2561    H264_CROP_PARAMS *psCrop,
2562    H264_SCALING_MATRIX_PARAMS __maybe_unused * psScalingMatrix)
2563{
2564    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
2565    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, 4);
2566
2567    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
2568
2569    // 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
2570    // Byte aligned (bit 32)
2571    tng__write_upto8bits_elements(pMTX_Header,
2572                                  aui32ElementPointers, (0 << 7) |                                                        // forbidden_zero_bit=0
2573                                  (0x3 << 5) |                                                                            // nal_ref_idc=01 (may be 11)
2574                                  (15),                                                                                           // nal_unit_type=15
2575                                  8);
2576
2577    // Byte aligned (bit 40)
2578    // profile_idc = 8 bits = 66 for BP (PROFILE_IDC_BP), 77 for MP (PROFILE_IDC_MP)
2579    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 118, 8);
2580
2581    // Byte aligned (bit 48)
2582    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (0 << 7) |     // constrain_set0_flag = 1 for MP + BP constraints
2583                                  (0 << 6) |                                                  // constrain_set1_flag  = 1 for MP + BP constraints
2584                                  (0 << 5) |                                                                                              // constrain_set2_flag = always 0 in BP/MP
2585                                  (0 << 4),                                                           // constrain_set3_flag = 1 for level 1b, 0 for others
2586                                  // reserved_zero_4bits = 0
2587                                  8);
2588
2589    // Byte aligned (bit 56)
2590    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (pSHParams->ucLevel == SH_LEVEL_1B) ? 11 : (IMG_UINT8)pSHParams->ucLevel, 8);                  // level_idc (8 bits) = 11 for 1b, 10xlevel for others
2591
2592    tng__generate_ue(pMTX_Header, aui32ElementPointers, MVC_SPS_ID);                // seq_parameter_Set_id = 1 FOR subset-SPS
2593    tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);         // chroma_format_idc = 1
2594    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);         // bit_depth_luma_minus8 = 0
2595    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);         // bit_depth_chroma_minus8 = 0
2596    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSHParams->bIsLossless ? 1 : 0, 1); // qpprime_y_zero_transform_bypass_flag = 0
2597
2598    if (pSHParams->bUseDefaultScalingList || pSHParams->seq_scaling_matrix_present_flag) {
2599        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);         // seq_scaling_matrix_present_flag
2600        if (!pSHParams->bUseDefaultScalingList) {
2601#ifdef _FIXME_
2602            H264_WriteBits_ScalingLists(pMTX_Header, aui32ElementPointers, psScalingMatrix, IMG_TRUE);
2603#endif
2604            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
2605        } else {
2606            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 8);         // seq_scaling_list_present_flag[i] = 0; 0 < i < 8
2607        }
2608    } else {
2609        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);         // seq_scaling_matrix_present_flag
2610    }
2611
2612    tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);         // log2_max_frame_num_minus4 = 1
2613    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);         // pic_order_cnt_type = 0
2614    tng__generate_ue(pMTX_Header, aui32ElementPointers, 2);         // log2_max_pic_order_cnt_Isb_minus4 = 2
2615
2616    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->max_num_ref_frames); //num_ref_frames ue(2), typically 2
2617    // Bytes aligned (bit 72)
2618    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
2619                                  (pSHParams->gaps_in_frame_num_value), // gaps_in_frame_num_value_allowed_Flag   - (1 bit)
2620                                  1);
2621
2622    ///**** GENERATES THE SECOND, VARIABLE LENGTH, ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
2623    ///**** ELEMENT BITCOUNT: xx
2624    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->ucWidth_in_mbs_minus1);                          //pic_width_in_mbs_minus1: ue(v) from 10 to 44 (176 to 720 pixel per row)
2625    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSHParams->ucHeight_in_maps_units_minus1);          //pic_height_in_maps_units_minus1: ue(v) Value from 8 to 35 (144 to 576 pixels per column)
2626    // We don't know the alignment at this point, so will have to use bit writing functions
2627
2628    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, pSHParams->ucFrame_mbs_only_flag, 1); // frame_mb_only_flag 1=frame encoding, 0=field encoding
2629
2630    if (!pSHParams->ucFrame_mbs_only_flag) // in the case of interlaced encoding
2631        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1); // mb_adaptive_frame_field_flag = 0 in Topaz(field encoding at the sequence level)
2632
2633    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); // direct_8x8_inference_flag=1 in Topaz
2634
2635    if (psCrop->bClip) {
2636        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);
2637        tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16LeftCropOffset);
2638        tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16RightCropOffset);
2639        tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16TopCropOffset);
2640        tng__generate_ue(pMTX_Header, aui32ElementPointers, psCrop->ui16BottomCropOffset);
2641
2642    } else {
2643        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);
2644    }
2645
2646    ///**** GENERATES THE THIRD ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE ****///
2647    ///**** ELEMENT BITCOUNT: xx
2648    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
2649                                  (pSHParams->VUI_Params_Present),                                        // vui_parameters_present_flag (VUI only in 1st sequence of stream)
2650                                  1);
2651    if (pSHParams->VUI_Params_Present > 0)
2652        tng__H264_writebits_VUI_params(pMTX_Header, aui32ElementPointers, &(pSHParams->VUI_Params));
2653
2654
2655    {
2656        int viewIdx = 0;
2657        int numViews = MAX_MVC_VIEWS;
2658        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); //bit_equal_to_one
2659
2660        // sequence parameter set MVC extension
2661        tng__generate_ue(pMTX_Header, aui32ElementPointers, (numViews - 1));     //num_views_minus1
2662        for (viewIdx = 0; viewIdx < numViews; viewIdx++) {
2663            tng__generate_ue(pMTX_Header, aui32ElementPointers, viewIdx);
2664        }
2665
2666        // anchor references
2667        for (viewIdx = 1; viewIdx < numViews; viewIdx++) {
2668            //tng__generate_ue( pMTX_Header, aui32ElementPointers, 0);     // num_anchor_refs_l0  = 0
2669            tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);      // num_anchor_refs_l0  = 1; view-1 refers to view-0
2670            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);      // anchor_ref_l0 = 0
2671
2672            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);      // num_anchor_refs_l1  = 0
2673        }
2674
2675        // non-anchor references
2676        for (viewIdx = 1; viewIdx < numViews; viewIdx++) {
2677            tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);      // num_non_anchor_refs_l0  = 0
2678            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);      // non_anchor_refs_l0  = 0
2679
2680            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);      // num_non_anchor_refs_l1  = 0
2681        }
2682
2683        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // num_level_values_signaled_minus1  = 0
2684
2685        //for(levelIdx=0; levelIdx<= 0; levelIdx++)
2686        {
2687            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, (pSHParams->ucLevel == SH_LEVEL_1B) ? 11 : (IMG_UINT8)pSHParams->ucLevel, 8);          // level_idc (8 bits) = 11 for 1b, 10xlevel for others
2688            tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // num_applicable_ops_minus1  = 0
2689            {
2690                tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 3); // applicable_ops_temporal_id  = 0
2691                tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);                  // applicable_op_num_target_views_minus1  = 0
2692                {
2693                    tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);              // applicable_op_target_view_id  = 0
2694                }
2695                tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);                  // applicable_op_num_views_minus1  = 0
2696            }
2697        }
2698
2699        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
2700                                      0,                    // mvc_vui_parameters_present_flag =0
2701                                      1);
2702
2703        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,
2704                                      0,                    // additional_extension2_flag =0
2705                                      1);
2706    }
2707
2708
2709    // Finally we need to align to the next byte
2710    // Tell MTX to insert the byte align field (we don't know final stream size for alignment at this point)
2711    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_INSERTBYTEALIGN_H264);
2712}
2713
2714
2715/*
2716******************************************************************************
2717 @Function              H264_PrepareMvcSequenceHeader
2718 @details
2719 Prepare an H264 SPS in a form for the MTX to encode into a bitstream.
2720 @param    pMTX_Header       : pointer to header structure to populate
2721 @param    uiPicWidthInMbs   : picture width in MBs
2722 @param    uiPicHeightInMbs  : picture height in MBs
2723 @param    bVuiParamsPresent : IMG_TRUE if VUI paramters present
2724 @param    psParams          : VUI parameters
2725 @param    psCrop                         : Pointer to crop parameter structure
2726 @param   psSHParams              : Pointer to sequence header params structure
2727 @return   None
2728******************************************************************************/
2729void tng__H264ES_prepare_mvc_sequence_header(
2730    void *pHeaderMemory,
2731    H264_CROP_PARAMS *psCropParams,
2732    IMG_UINT16 ui16PictureWidth,
2733    IMG_UINT16 ui16PictureHeight,
2734    IMG_UINT32 ui32CustomQuantMask,
2735    IMG_UINT8 ui8ProfileIdc,
2736    IMG_UINT8 ui8LevelIdc,
2737    IMG_UINT8 ui8FieldCount,
2738    IMG_UINT8 ui8MaxNumRefFrames,
2739    IMG_BOOL  bPpsScaling,
2740    IMG_BOOL  bUseDefaultScalingList,
2741    IMG_BOOL  bEnableLossless,
2742    IMG_BOOL  __maybe_unused bASO)
2743{
2744    H264_SEQUENCE_HEADER_PARAMS sSHParams;
2745    MTX_HEADER_PARAMS * pMTX_Header;
2746    MTX_HEADER_ELEMENT *This_Element;
2747    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2748    pMTX_Header = (MTX_HEADER_PARAMS *) pHeaderMemory;
2749
2750#if HEADERS_VERBOSE_OUTPUT
2751    drv_debug_msg(VIDEO_DEBUG_GENERAL, "\n\n**********************************************************************\n");
2752    drv_debug_msg(VIDEO_DEBUG_GENERAL, "******** HOST FIRMWARE ROUTINES TO PASS HEADERS AND TOKENS TO MTX******\n");
2753    drv_debug_msg(VIDEO_DEBUG_GENERAL, "**********************************************************************\n\n");
2754#endif
2755
2756    // Builds a sequence, picture and slice header with from the given inputs parameters (start of new frame)
2757    // Essential we initialise our header structures before building
2758    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
2759    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
2760    aui32ElementPointers[0] = This_Element;
2761
2762    memset(&sSHParams, 0, sizeof(H264_SEQUENCE_HEADER_PARAMS));
2763
2764    sSHParams.ucProfile = ui8ProfileIdc - 5;
2765    sSHParams.ucLevel = (ui8LevelIdc != 111) ? ui8LevelIdc : SH_LEVEL_1B;
2766    sSHParams.ucWidth_in_mbs_minus1 = (IMG_UINT8)((ui16PictureWidth >> 4)- 1);
2767    sSHParams.ucHeight_in_maps_units_minus1 = (IMG_UINT8)((ui16PictureHeight >> 4) - 1);
2768    sSHParams.gaps_in_frame_num_value = IMG_FALSE;
2769    sSHParams.VUI_Params_Present = IMG_FALSE;
2770    sSHParams.ucFrame_mbs_only_flag = (ui8FieldCount > 1) ? IMG_FALSE : IMG_TRUE;
2771    sSHParams.seq_scaling_matrix_present_flag = (bPpsScaling) ? IMG_FALSE : (IMG_UINT8)(ui32CustomQuantMask);
2772    sSHParams.bUseDefaultScalingList = (bPpsScaling) ? IMG_FALSE : bUseDefaultScalingList;
2773    sSHParams.max_num_ref_frames = ui8MaxNumRefFrames;
2774    sSHParams.bIsLossless = bEnableLossless;
2775    sSHParams.log2_max_pic_order_cnt = 6;
2776#ifdef _TOPAZHP_PDUMP_
2777    tng_trace_seq_header_params(&sSHParams);
2778#endif
2779    tng__H264ES_writebits_mvc_sequence_header(pMTX_Header, aui32ElementPointers, &sSHParams, psCropParams, NULL);
2780    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
2781    return ;
2782}
2783
2784void tng__H264ES_prepare_picture_header(
2785    void *pHeaderMemory,
2786    IMG_BOOL    bCabacEnabled,
2787    IMG_BOOL    b_8x8transform,
2788    IMG_BOOL    bIntraConstrained,
2789    IMG_INT8    i8CQPOffset,
2790    IMG_BOOL    bWeightedPrediction,
2791    IMG_UINT8   ui8WeightedBiPred,
2792    IMG_BOOL    bMvcPPS,
2793    IMG_BOOL    bScalingMatrix,
2794    IMG_BOOL    bScalingLists)
2795{
2796    MTX_HEADER_PARAMS *pMTX_Header;
2797    H264_PICTURE_HEADER_PARAMS sPHParams;
2798
2799    /* Route output elements to memory provided */
2800    pMTX_Header = (MTX_HEADER_PARAMS *) pHeaderMemory;
2801    /* Builds a sequence, picture and slice header with from the given inputs parameters (start of new frame)
2802     * Essential we initialise our header structures before building
2803     */
2804    MTX_HEADER_ELEMENT *This_Element;
2805    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2806    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
2807    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
2808    aui32ElementPointers[0] = This_Element;
2809
2810    memset(&sPHParams, 0, sizeof(H264_PICTURE_HEADER_PARAMS));
2811
2812    sPHParams.pic_parameter_set_id = bMvcPPS ? MVC_PPS_ID : 0;
2813    sPHParams.seq_parameter_set_id = bMvcPPS ? MVC_SPS_ID : 0;
2814    sPHParams.entropy_coding_mode_flag = bCabacEnabled ? 1 : 0;
2815    sPHParams.weighted_pred_flag = bWeightedPrediction;
2816    sPHParams.weighted_bipred_idc = ui8WeightedBiPred;
2817    sPHParams.chroma_qp_index_offset = i8CQPOffset;
2818    sPHParams.constrained_intra_pred_flag = bIntraConstrained ? 1 : 0;
2819    sPHParams.transform_8x8_mode_flag = b_8x8transform ? 1 : 0;
2820    sPHParams.pic_scaling_matrix_present_flag = bScalingMatrix ? 1 : 0;
2821    sPHParams.bUseDefaultScalingList = !bScalingLists;
2822    sPHParams.second_chroma_qp_index_offset = i8CQPOffset;
2823#ifdef _TOPAZHP_PDUMP_
2824    tng_trace_pic_header_params(&sPHParams);
2825#endif
2826    tng__H264ES_writebits_picture_header(pMTX_Header, aui32ElementPointers, &sPHParams, NULL);
2827    /* Has been used as an index, so need to add 1 for a valid element count */
2828    pMTX_Header->ui32Elements++;
2829    return ;
2830}
2831
2832void tng__H264_prepare_slice_header(
2833    IMG_UINT32 *pHeaderMemory,
2834    IMG_BOOL        bIntraSlice,
2835    IMG_BOOL        bInterBSlice,
2836    IMG_BOOL        bMultiRef,
2837    IMG_UINT8       ui8DisableDeblockingFilterIDC,
2838    IMG_UINT32      ui32DisplayFrameNumber,
2839    IMG_UINT32      ui32FrameNumId,
2840    IMG_UINT32      uiFirst_MB_Address,
2841    IMG_UINT32      __maybe_unused uiMBSkipRun,
2842    IMG_BOOL        bCabacEnabled,
2843    IMG_BOOL        bIsInterlaced,
2844    IMG_UINT8       ui8FieldNum,
2845    WEIGHTED_PREDICTION_VALUES *pWeightedSetup,
2846    IMG_BOOL        bIsLongTermRef
2847)
2848{
2849    H264_SLICE_HEADER_PARAMS SlHParams;
2850    MTX_HEADER_PARAMS *pMTX_Header;
2851    /* Route output elements to memory provided */
2852    pMTX_Header = (MTX_HEADER_PARAMS *) pHeaderMemory;
2853
2854    memset(&SlHParams, 0, sizeof(H264_SLICE_HEADER_PARAMS));
2855
2856
2857    SlHParams.ui8Start_Code_Prefix_Size_Bytes = 4;
2858    /* pcb -        I think that this is more correct now*/
2859    SlHParams.SliceFrame_Type = bIntraSlice ? (((ui32FrameNumId % (1 << 5)) == 0) ?
2860                                SLHP_IDR_SLICEFRAME_TYPE : SLHP_I_SLICEFRAME_TYPE) : (bInterBSlice ? SLHP_B_SLICEFRAME_TYPE : SLHP_P_SLICEFRAME_TYPE);
2861    /*
2862    if (bIntraSlice) {
2863        if ((ui32FrameNumId%(1<<5))==0)
2864            SlHParams.SliceFrame_Type = SLHP_IDR_SLICEFRAME_TYPE;
2865        else
2866            SlHParams.SliceFrame_Type = SLHP_I_SLICEFRAME_TYPE;
2867    } else {
2868        if (bInterBSlice)
2869            SlHParams.SliceFrame_Type = SLHP_B_SLICEFRAME_TYPE;
2870        else
2871            SlHParams.SliceFrame_Type = SLHP_P_SLICEFRAME_TYPE;
2872    }
2873    */
2874    SlHParams.Frame_Num_DO   = (IMG_UINT8) ui32FrameNumId % (1 << 5);
2875    SlHParams.Idr_Pic_Id     = (IMG_UINT8)(ui32DisplayFrameNumber & 1);
2876    SlHParams.Picture_Num_DO = (IMG_UINT8)((ui32DisplayFrameNumber % (1 << 5)) * 2);
2877
2878    SlHParams.First_MB_Address =  uiFirst_MB_Address;
2879    SlHParams.Disable_Deblocking_Filter_Idc = (IMG_UINT8) ui8DisableDeblockingFilterIDC;
2880    SlHParams.bPiCInterlace = bIsInterlaced;
2881    SlHParams.bFieldType    = ui8FieldNum;
2882    SlHParams.iDebAlphaOffsetDiv2   = 0;
2883    SlHParams.iDebBetaOffsetDiv2    = 0;
2884
2885    if (bMultiRef)
2886        SlHParams.num_ref_idx_l0_active_minus1 = 1;
2887    else
2888        SlHParams.num_ref_idx_l0_active_minus1 = 0;
2889
2890    SlHParams.weighted_pred_flag            = pWeightedSetup ? pWeightedSetup->weighted_pred_flag             : 0;
2891    SlHParams.weighted_bipred_idc   = pWeightedSetup ? pWeightedSetup->weighted_bipred_idc            : 0;
2892    SlHParams.luma_log2_weight_denom        = pWeightedSetup ? pWeightedSetup->luma_log2_weight_denom         : 0;
2893    SlHParams.chroma_log2_weight_denom      = pWeightedSetup ? pWeightedSetup->chroma_log2_weight_denom : 0;
2894    SlHParams.luma_weight_l0_flag[0]        = pWeightedSetup ? pWeightedSetup->weight_flag[0][0]                      : 0;
2895    SlHParams.luma_weight_l0[0]             = pWeightedSetup ? pWeightedSetup->weight[0][0]                   : 0;
2896    SlHParams.luma_offset_l0[0]             = pWeightedSetup ? pWeightedSetup->offset[0][0]                   : 0;
2897    SlHParams.chroma_weight_l0_flag[0]      = pWeightedSetup ? pWeightedSetup->weight_flag[1][0]                      : 0;
2898    SlHParams.chromaB_weight_l0[0]          = pWeightedSetup ? pWeightedSetup->weight[1][0]                   : 0;
2899    SlHParams.chromaB_offset_l0[0]          = pWeightedSetup ? pWeightedSetup->offset[1][0]                   : 0;
2900    SlHParams.chromaR_weight_l0[0]          = pWeightedSetup ? pWeightedSetup->weight[2][0]                   : 0;
2901    SlHParams.chromaR_offset_l0[0]          = pWeightedSetup ? pWeightedSetup->offset[2][0]                   : 0;
2902    SlHParams.luma_weight_l0_flag[1]        = pWeightedSetup ? pWeightedSetup->weight_flag[0][1]                      : 0;
2903    SlHParams.luma_weight_l0[1]             = pWeightedSetup ? pWeightedSetup->weight[0][1]                   : 0;
2904    SlHParams.luma_offset_l0[1]             = pWeightedSetup ? pWeightedSetup->offset[0][1]                   : 0;
2905    SlHParams.chroma_weight_l0_flag[1]      = pWeightedSetup ? pWeightedSetup->weight_flag[1][1]                      : 0;
2906    SlHParams.chromaB_weight_l0[1]          = pWeightedSetup ? pWeightedSetup->weight[1][1]                   : 0;
2907    SlHParams.chromaB_offset_l0[1]          = pWeightedSetup ? pWeightedSetup->offset[1][1]                   : 0;
2908    SlHParams.chromaR_weight_l0[1]          = pWeightedSetup ? pWeightedSetup->weight[2][1]                   : 0;
2909    SlHParams.chromaR_offset_l0[1]          = pWeightedSetup ? pWeightedSetup->offset[2][1]                   : 0;
2910
2911    SlHParams.bIsLongTermRef = bIsLongTermRef;
2912    tng__H264_getelements_slice_header(pMTX_Header, &SlHParams, bCabacEnabled);
2913
2914    /*
2915        {
2916            IMG_UINT32      *pMTX_Header_Mem = (IMG_UINT32 *)mtx_hdr;
2917            // rhk: first insert normal header.
2918            tng__H264_getelements_slice_header(mtx_hdr, &SlHParams, bCabacEnabled, uiIdrPicId);
2919
2920            // put a marker to indicate that this is a complex header
2921            // note that first "int" in the buffer is used for number of elements
2922            // which is not going to be more than 255
2923            *pMTX_Header_Mem |= 0x100;
2924
2925            // rhk: insert skipped frame header at an offset of 128 bytes
2926            pMTX_Header_Mem += (HEADER_SIZE >> 3);  // get a pointer to the second half of memory
2927            mtx_hdr = (MTX_HEADER_PARAMS *)pMTX_Header_Mem;
2928            tng__H264_getelements_skip_P_slice(mtx_hdr, &SlHParams, uiMBSkipRun, bCabacEnabled);
2929        }
2930    */
2931}
2932
2933void tng__MPEG4_prepare_sequence_header(
2934    void *pHeaderMemory,
2935    IMG_BOOL bBFrame,
2936    MPEG4_PROFILE_TYPE sProfile,
2937    IMG_UINT8 Profile_and_level_indication,
2938    FIXED_VOP_TIME_TYPE sFixed_vop_time_increment,
2939    IMG_UINT32 Picture_Width_Pixels,
2940    IMG_UINT32 Picture_Height_Pixels,
2941    VBVPARAMS * psVBVParams,
2942    IMG_UINT32 VopTimeResolution)
2943{
2944    MTX_HEADER_PARAMS *mtx_hdr;
2945
2946    /* Route output elements to memory provided */
2947    mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMemory;
2948    /* Builds a single MPEG4 video sequence header from the given parameters */
2949
2950    /* Essential we initialise our header structures before building */
2951    MTX_HEADER_ELEMENT *This_Element;
2952    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
2953    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2954    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
2955    aui32ElementPointers[0] = This_Element;
2956
2957    tng__MPEG4_writebits_sequence_header(mtx_hdr,
2958        				 aui32ElementPointers,
2959        				 bBFrame,
2960					 sProfile,
2961       				 	 Profile_and_level_indication,
2962       				 	 sFixed_vop_time_increment,
2963        				 Picture_Width_Pixels,
2964        				 Picture_Height_Pixels,
2965        				 psVBVParams,
2966					 VopTimeResolution);
2967
2968    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
2969
2970}
2971
2972void tng__MPEG4_prepare_vop_header(
2973    IMG_UINT32 *pHeaderMem,
2974    IMG_BOOL bIsVOP_coded,
2975    IMG_UINT32 VOP_time_increment,
2976    IMG_UINT8 sSearch_range,
2977    IMG_UINT8 eVop_Coding_Type,
2978    IMG_UINT32 VopTimeResolution)
2979{
2980    MTX_HEADER_PARAMS *mtx_hdr;
2981
2982    mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMem;
2983
2984    /* Builds a single MPEG4 VOP (picture) header from the given parameters */
2985    /* Essential we initialise our header structures before building */
2986    MTX_HEADER_ELEMENT *This_Element;
2987    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
2988    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
2989    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
2990    aui32ElementPointers[0] = This_Element;
2991
2992    /* Frame QScale no longer written here as it is inserted by MTX later
2993     * (add as parameter to MTX_Send_Elements_To_VLC)
2994     */
2995    tng__MPEG4_writebits_VOP_header(
2996        mtx_hdr, aui32ElementPointers, bIsVOP_coded,
2997        VOP_time_increment,
2998        sSearch_range,
2999        eVop_Coding_Type,
3000        VopTimeResolution);
3001
3002    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
3003
3004}
3005
3006void tng__H263_prepare_sequence_header(
3007    IMG_UINT32 *pHeaderMem,
3008    IMG_UINT8 Profile_and_level_indication)
3009{
3010    MTX_HEADER_PARAMS *mtx_hdr;
3011
3012    mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMem;
3013
3014    /* Builds a single H263 video sequence header from the given parameters */
3015
3016    /* Essential we initialise our header structures before building */
3017    MTX_HEADER_ELEMENT *This_Element;
3018    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3019    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
3020    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
3021    aui32ElementPointers[0] = This_Element;
3022
3023    H263_writebits_VideoSequenceHeader(mtx_hdr, aui32ElementPointers, Profile_and_level_indication);
3024
3025    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
3026
3027}
3028
3029void tng__H263_prepare_picture_header(
3030    IMG_UINT32 *pHeaderMem,
3031    IMG_UINT8 Temporal_Ref,
3032    H263_PICTURE_CODING_TYPE PictureCodingType,
3033    H263_SOURCE_FORMAT_TYPE SourceFormatType,
3034    IMG_UINT8 FrameRate,
3035    IMG_UINT16 PictureWidth,
3036    IMG_UINT16 PictureHeigth)
3037{
3038    MTX_HEADER_PARAMS *mtx_hdr;
3039
3040    mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMem;
3041
3042    /* Essential we initialise our header structures before building */
3043    MTX_HEADER_ELEMENT *This_Element;
3044    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3045    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
3046    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
3047    aui32ElementPointers[0] = This_Element;
3048
3049    H263_writebits_VideoPictureHeader(
3050        mtx_hdr, aui32ElementPointers,
3051        Temporal_Ref,
3052        PictureCodingType,
3053        SourceFormatType,
3054        FrameRate,
3055        PictureWidth,
3056        PictureHeigth);
3057
3058    mtx_hdr->ui32Elements++; /* Has been used as an index, so need to add 1 for a valid element count */
3059}
3060
3061void tng__H263_prepare_GOBslice_header(
3062    IMG_UINT32 *pHeaderMem,
3063    IMG_UINT8 GOBNumber,
3064    IMG_UINT8 GOBFrameId)
3065{
3066    MTX_HEADER_PARAMS *mtx_hdr;
3067
3068    mtx_hdr = (MTX_HEADER_PARAMS *) pHeaderMem;
3069
3070    /* Essential we initialise our header structures before building */
3071    MTX_HEADER_ELEMENT *This_Element;
3072    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3073    mtx_hdr->ui32Elements = ELEMENTS_EMPTY;
3074    This_Element = (MTX_HEADER_ELEMENT *) mtx_hdr->asElementStream;
3075    aui32ElementPointers[0] = This_Element;
3076
3077    H263_writebits_GOBSliceHeader(mtx_hdr, aui32ElementPointers, GOBNumber, GOBFrameId);
3078
3079    mtx_hdr->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
3080
3081    /* silent the warning message */
3082    (void)Show_Bits;
3083    (void)Show_Elements;
3084    /*
3085    (void)tng__H264_writebits_SEI_rbspheader;
3086    (void)tng__H264_getelements_skip_B_slice;
3087    (void)tng__H264_getelements_backward_zero_B_slice;
3088    (void)tng__H264_getelements_rbsp_ATE_only;
3089    (void)tng_MPEG4_getelements_video_packet_header;
3090    */
3091}
3092
3093void tng__H264ES_notforsims_writebits_extension_sliceheader(
3094    MTX_HEADER_PARAMS *pMTX_Header,
3095    MTX_HEADER_ELEMENT **aui32ElementPointers,
3096    H264_SLICE_HEADER_PARAMS *pSlHParams,
3097    IMG_BOOL bCabacEnabled, IMG_BOOL bIsIDR)
3098{
3099    bStartNextRawDataElement = IMG_FALSE;
3100
3101    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
3102
3103    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, pSlHParams->ui8Start_Code_Prefix_Size_Bytes); //Can be 3 or 4 bytes - always 4 bytes in our implementations
3104
3105    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3106    ///**** ELEMENT BITCOUNT: 8
3107
3108    // StartCodePrefix Pregenerated in: Build_H264_4Byte_StartCodePrefix_Element() (4 or 3 bytes)
3109    //(3 bytes when slice is first in a picture without sequence/picture_header before picture
3110    // Byte aligned (bit 32 or 24)
3111    // NOTE: Slice_Type and Frame_Type are always the same, hence SliceFrame_Type
3112    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);   // forbidden_zero_bit
3113
3114    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REFERENCE); //MTX fills this value in
3115    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3116
3117    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 20, 5);    // nal_unit_type for coded_slice_extension
3118
3119
3120    //if(nal_unit_type == 14 || nal_unit_type == 20)
3121    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);   // SVC extension flag
3122
3123    // nal_unit_header_mvc_extension()
3124    {
3125        if (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) {
3126            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // non_idr_flag flag
3127        } else if ((pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE) && bIsIDR) {
3128            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // non_idr_flag flag
3129        } else {
3130            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    1, 1);   // non_idr_flag flag
3131        }
3132
3133        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 6);   // priority_id flag
3134        tng__write_upto32bits_elements(pMTX_Header, aui32ElementPointers,    1, 10);   // view_id = hardcoded to 1 for dependent view
3135
3136        //tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 3);   // temporal_id flag
3137        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_TEMPORAL_ID); // temporal_id flag
3138        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_ANCHOR_PIC_FLAG); // anchor_pic_flag
3139
3140        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3141
3142        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    0, 1);   // interview flag is always FALSE for dependent frames
3143
3144        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers,    1, 1);   // reserved one bit
3145    }
3146
3147    // slice header
3148    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_CURRMBNR); //MTX fills this value in
3149
3150    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3151
3152    ///**** GENERATES THE SECOND ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3153    /* The following is slice parameter set in BP/MP */
3154    //tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32) pSlHParams->First_MB_Address);                               //first_mb_in_slice = First MB address in slice: ue(Range 0 -  1619)
3155    tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32)((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) ? SLHP_I_SLICEFRAME_TYPE : pSlHParams->SliceFrame_Type));                                    //slice_type ue(v): 0 for P-slice, 1 for B-slice, 2 for I-slice
3156    // kab: //not clean change from IDR to intra, IDR should have separate flag
3157
3158    tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);  // pic_parameter_set_id = 1 for dependent view
3159
3160    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_FRAME_NUM); // Insert token to tell MTX to insert frame_num
3161    bStartNextRawDataElement = IMG_TRUE;
3162
3163    if ((pSlHParams->bPiCInterlace) || (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE)) {
3164        //tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3165
3166        // interlaced encoding
3167        if (pSlHParams->bPiCInterlace) {
3168            CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3169            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);                                          // field_pic_flag = 1
3170            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_BOTTOM_FIELD); // Insert token to tell MTX to insert BOTTOM_FIELD flag if required
3171            //tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3172            bStartNextRawDataElement = IMG_TRUE;
3173        }
3174    }
3175
3176    if ((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) || (bIsIDR)) {
3177        CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3178        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); // idr_pic_id ue(v) = 0 (1b) in Topaz
3179    }
3180
3181    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_PIC_ORDER_CNT); // Insert token to tell MTX to insert pic_order_cnt_lsb
3182    bStartNextRawDataElement = IMG_TRUE;
3183
3184    if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE)
3185        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_DIRECT_SPATIAL_MV_FLAG); // Insert token to tell MTX to insert direct_spatial_mv_pred_flag
3186
3187    if (pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE) {
3188        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_NUM_REF_IDX_ACTIVE);
3189        bStartNextRawDataElement = IMG_TRUE;
3190    } else if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE) {
3191        CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3192        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);             // num_ref_idx_active_override_flag (1 bit) = 0 in Topaz
3193    }
3194
3195    // reference picture list modification
3196    if (pSlHParams->SliceFrame_Type != SLHP_I_SLICEFRAME_TYPE && pSlHParams->SliceFrame_Type != SLHP_IDR_SLICEFRAME_TYPE) {
3197        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REORDER_L0); // Insert token to tell MTX to insert BOTTOM_FIELD flag if required
3198        //tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3199        bStartNextRawDataElement = IMG_TRUE;
3200    }
3201
3202    if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE)        {
3203        CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3204        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);                                                                 // ref_pic_list_ordering_flag_l1 (1 bit) = 0, no reference picture ordering in Topaz
3205    }
3206
3207    // WEIGHTED PREDICTION
3208    /*      tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SLICEWEIGHTEDPREDICTIONSTRUCT);
3209        bStartNextRawDataElement = IMG_TRUE;*/
3210
3211    if ((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) || (bIsIDR)) {
3212        CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3213        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);                                                                 // no_output_of_prior_pics_flag (1 bit) = 0
3214        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);                                                                 // long_term_reference_flag (1 bit) = 0
3215    } else {
3216        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_ADAPTIVE); //MTX fills this value in
3217        //tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3218        bStartNextRawDataElement = IMG_TRUE;
3219    }
3220
3221    if (bCabacEnabled && ((SLHP_P_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type) ||
3222                          (SLHP_B_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type))) {
3223        CheckStartRawDataElement(pMTX_Header, aui32ElementPointers);
3224        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // hard code cabac_init_idc value of 0
3225    }
3226    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SQP); //MTX fills this value in
3227    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3228
3229    ///**** GENERATES ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3230    ///**** ELEMENT BITCOUNT: 11
3231    // Next field is generated on MTX with a special commnad (not ELEMENT_RAW) - so not defined here
3232    //pucHS=tng__generate_se(pucHS, puiBitPos, pSlHParams->Slice_QP_Delta); //slice_qp_delta se(v) = SliceQPy - (pic_init_qp_minus26+26)
3233    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->Disable_Deblocking_Filter_Idc); //disable_deblocking_filter_idc ue(v) = 2?
3234    if (pSlHParams->Disable_Deblocking_Filter_Idc != 1) {
3235        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebAlphaOffsetDiv2); //slice_alpha_c0_offset_div2 se(v) = 0 (1b) in Topaz
3236        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebBetaOffsetDiv2); //slice_beta_offset_div2 se(v) = 0 (1b) in Topaz
3237    }
3238    //num_slice_groups_minus1 ==0 in Topaz, so no slice_group_change_cycle field here
3239    // no byte alignment at end of slice headers
3240}
3241
3242
3243/*****************************************************************************
3244******************************************************************************/
3245static void tng__H264ES_notforsims_writebits_slice_header(
3246    MTX_HEADER_PARAMS *pMTX_Header,
3247    MTX_HEADER_ELEMENT **aui32ElementPointers,
3248    H264_SLICE_HEADER_PARAMS *pSlHParams,
3249    IMG_BOOL bCabacEnabled, IMG_BOOL bIsIDR)
3250{
3251    bStartNextRawDataElement = IMG_FALSE;
3252    unsigned char* pdg = (unsigned char*)pMTX_Header;
3253
3254    if (pSlHParams->ui16MvcViewIdx == (IMG_UINT16)(NON_MVC_VIEW)) {
3255        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_RAWDATA);
3256    } else if (pSlHParams->ui16MvcViewIdx == MVC_BASE_VIEW_IDX) {
3257        tng__insert_prefix_nal_header(pMTX_Header, aui32ElementPointers,
3258                                      pSlHParams, bCabacEnabled);
3259        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_STARTCODE_MIDHDR);
3260    } else {
3261        //Insert
3262        tng__H264ES_notforsims_writebits_extension_sliceheader(pMTX_Header, aui32ElementPointers,
3263                pSlHParams, bCabacEnabled, bIsIDR);
3264        return;
3265    }
3266
3267    tng__H264_writebits_startcode_prefix_element(pMTX_Header, aui32ElementPointers, pSlHParams->ui8Start_Code_Prefix_Size_Bytes); //Can be 3 or 4 bytes - always 4 bytes in our implementations
3268
3269    ///**** GENERATES THE FIRST ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3270    ///**** ELEMENT BITCOUNT: 8
3271
3272    // StartCodePrefix Pregenerated in: Build_H264_4Byte_StartCodePrefix_Element() (4 or 3 bytes)
3273    //(3 bytes when slice is first in a picture without sequence/picture_header before picture
3274    // Byte aligned (bit 32 or 24)
3275    // NOTE: Slice_Type and Frame_Type are always the same, hence SliceFrame_Type
3276
3277    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);   // forbidden_zero_bit
3278
3279    // nal_ref_idc, 0x03 for IDR slice, for non-IDR slice, fw chose a value
3280    //tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE ? 3 : ELEMENT_REFERENCE)), 2);
3281    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REFERENCE);
3282    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3283
3284    tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, ((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE ? 5 : 1)),                   // nal_unit_tpye (5 bits) = I-frame IDR, and 1 for  rest
3285                                  5);
3286
3287    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_CURRMBNR); //MTX fills this value in
3288    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3289
3290
3291    ///**** GENERATES THE SECOND ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3292    /* The following is slice parameter set in BP/MP */
3293    //tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32) pSlHParams->First_MB_Address);                               //first_mb_in_slice = First MB address in slice: ue(Range 0 -  1619)
3294    tng__generate_ue(pMTX_Header, aui32ElementPointers, (IMG_UINT32)((pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE) ? SLHP_I_SLICEFRAME_TYPE : pSlHParams->SliceFrame_Type));                                    //slice_type ue(v): 0 for P-slice, 1 for B-slice, 2 for I-slice
3295    // kab: //not clean change from IDR to intra, IDR should have separate flag
3296    if (pSlHParams->ui16MvcViewIdx != (IMG_UINT16)(NON_MVC_VIEW))
3297        tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->ui16MvcViewIdx);  // pic_parameter_set_id = 0
3298    else
3299        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);  // pic_parameter_set_id = 0
3300
3301    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_FRAME_NUM); // Insert token to tell MTX to insert frame_num
3302
3303    if ((pSlHParams->bPiCInterlace) || (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE)) {
3304        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3305        // interlaced encoding
3306        if (pSlHParams->bPiCInterlace) {
3307            tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1);                                          // field_pic_flag = 1
3308            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_BOTTOM_FIELD); // Insert token to tell MTX to insert BOTTOM_FIELD flag if required
3309            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3310        }
3311
3312        if (pSlHParams->SliceFrame_Type == SLHP_IDR_SLICEFRAME_TYPE)
3313            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_IDR_PIC_ID);       // idr_pic_id ue(v)
3314    }
3315
3316    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_PIC_ORDER_CNT); // Insert token to tell MTX to insert pic_order_cnt_lsb
3317
3318    if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE)
3319        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_DIRECT_SPATIAL_MV_FLAG); // Insert token to tell MTX to insert direct_spatial_mv_pred_flag
3320
3321    if (pSlHParams->SliceFrame_Type == SLHP_P_SLICEFRAME_TYPE) {
3322        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_NUM_REF_IDX_ACTIVE); // Insert token to tell MTX to insert override for number of active references
3323    } else if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE) {
3324        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3325        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 0, 1);                                                                 // num_ref_idx_active_override_flag (1 bit) = 0
3326    }
3327
3328    if (pSlHParams->SliceFrame_Type != SLHP_I_SLICEFRAME_TYPE &&
3329        pSlHParams->SliceFrame_Type != SLHP_IDR_SLICEFRAME_TYPE) {
3330        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REORDER_L0); // Insert token to tell MTX to insert reference list 0 reordering
3331        if (pSlHParams->SliceFrame_Type == SLHP_B_SLICEFRAME_TYPE)
3332            tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_REORDER_L1); // Insert token to tell MTX to insert reference list 1 reordering
3333    }
3334
3335
3336    // WEIGHTED PREDICTION
3337    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SLICEWEIGHTEDPREDICTIONSTRUCT);
3338    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3339
3340    if (pSlHParams->bReferencePicture && pSlHParams->bIsLongTermRef) {
3341        tng__write_upto8bits_elements(pMTX_Header, aui32ElementPointers, 1, 1); // adaptive_ref_pic_marking_mode_flag (1 bit) = 0
3342
3343        // Clear any existing long-term reference
3344        tng__generate_ue(pMTX_Header, aui32ElementPointers, 5);                                 // memory_management_control_operation
3345
3346        // Allow a single long-term reference
3347        tng__generate_ue(pMTX_Header, aui32ElementPointers, 4);                                 // memory_management_control_operation
3348        tng__generate_ue(pMTX_Header, aui32ElementPointers, 1);                                 // max_long_term_frame_idx_plus1
3349
3350        // Set current picture as the long-term reference
3351        tng__generate_ue(pMTX_Header, aui32ElementPointers, 6);                                 // memory_management_control_operation
3352        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);                                 // long_term_frame_idx
3353
3354        // End
3355        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0);                                 // memory_management_control_operation
3356    } else {
3357        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_ADAPTIVE); //MTX fills this value in
3358        tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3359    }
3360
3361    if (bCabacEnabled && ((SLHP_P_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type) ||
3362                          (SLHP_B_SLICEFRAME_TYPE == pSlHParams->SliceFrame_Type))) {
3363        tng__generate_ue(pMTX_Header, aui32ElementPointers, 0); // hard code cabac_init_idc value of 0
3364    }
3365    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_SQP); //MTX fills this value in
3366    tng__insert_element_token(pMTX_Header, aui32ElementPointers, ELEMENT_RAWDATA);
3367
3368    ///**** GENERATES ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE ****///
3369    ///**** ELEMENT BITCOUNT: 11
3370    // Next field is generated on MTX with a special commnad (not ELEMENT_RAW) - so not defined here
3371    //pucHS=tng__generate_se(pucHS, puiBitPos, pSlHParams->Slice_QP_Delta); //slice_qp_delta se(v) = SliceQPy - (pic_init_qp_minus26+26)
3372    tng__generate_ue(pMTX_Header, aui32ElementPointers, pSlHParams->Disable_Deblocking_Filter_Idc); //disable_deblocking_filter_idc ue(v) = 2?
3373
3374    if (pSlHParams->Disable_Deblocking_Filter_Idc != 1) {
3375        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebAlphaOffsetDiv2); //slice_alpha_c0_offset_div2 se(v) = 0 (1b) in Topaz
3376        tng__generate_se(pMTX_Header, aui32ElementPointers, pSlHParams->iDebBetaOffsetDiv2); //slice_beta_offset_div2 se(v) = 0 (1b) in Topaz
3377    }
3378    //num_slice_groups_minus1 ==0 in Topaz, so no slice_group_change_cycle field here
3379    // no byte alignment at end of slice headers
3380}
3381
3382/******************************************************************************
3383 @Function              H264_NOTFORSIMS_PrepareSliceHeader
3384 @details
3385 Sim guys, DO NOT EVER USE THIS FUNCTION!
3386 Prepare an H264 slice header in a form for the MTX to encode into a
3387 bitstream.
3388 @param    pMTX_Header        : pointer to header structure to populate
3389 @param    bIntraSlice        : IMG_TRUE if this is an IDR or I slice
3390 @param    bInterBSlice        : IMG_TRUE if this is a B Frame slice
3391 @param    ui8DisableDeblockingFilterIDC : syntax element
3392 @param    ui32FrameNumId      : syntax element (used for references)
3393 @param    uiFirst_MB_Address : first_mb_in_slice syntax element
3394 @param    uiMBSkipRun        : number of MBs to skip
3395 @param    bCabacEnabled      : IMG_TRUE to use CABAC
3396 @param    bIsInterlaced      : IMG_TRUE for interlaced slices
3397 @param    bIsIDR             : IMG_TRUE if this is an IDR slice
3398 @param    bIsLongTermRef     : IMG_TRUE if the frame is to be used as a long-term reference
3399 @return   None
3400******************************************************************************/
3401
3402void tng__H264ES_notforsims_prepare_sliceheader(
3403    IMG_UINT8      *slice_mem_p,
3404    IMG_UINT32      ui32SliceType,
3405    IMG_UINT8       ui8DisableDeblockingFilterIDC,
3406    IMG_UINT32      uiFirst_MB_Address,
3407    IMG_UINT32      __maybe_unused uiMBSkipRun,
3408    IMG_BOOL        bCabacEnabled,
3409    IMG_BOOL        bIsInterlaced,
3410    IMG_UINT16      ui16MvcViewIdx,
3411    IMG_BOOL        bIsLongTermRef
3412)
3413{
3414    SLICE_PARAMS *slice_temp_p = (SLICE_PARAMS*)slice_mem_p;
3415    MTX_HEADER_PARAMS *pMTX_Header = (MTX_HEADER_PARAMS *) &(slice_temp_p->sSliceHdrTmpl);
3416    H264_SLICE_HEADER_PARAMS SlHParams;
3417    MTX_HEADER_ELEMENT *This_Element;
3418    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3419    IMG_FRAME_TEMPLATE_TYPE eSliceType = (IMG_FRAME_TEMPLATE_TYPE)ui32SliceType;
3420    IMG_BOOL bIntraSlice = ((eSliceType == IMG_FRAME_IDR) || (eSliceType == IMG_FRAME_INTRA));
3421    IMG_BOOL bInterBSlice = (eSliceType == IMG_FRAME_INTER_B);
3422    IMG_BOOL bIsIDR = ((eSliceType == IMG_FRAME_IDR) || (eSliceType == IMG_FRAME_INTER_P_IDR));
3423
3424    memset(&SlHParams, 0, sizeof(H264_SLICE_HEADER_PARAMS));
3425
3426    SlHParams.ui8Start_Code_Prefix_Size_Bytes = 4;
3427    /* pcb -  I think that this is more correct now  -- This should also work for IDR-P frames which will be marked as SLHP_P_SLICEFRAME_TYPE */
3428    SlHParams.SliceFrame_Type = bIntraSlice ? (bIsIDR ? SLHP_IDR_SLICEFRAME_TYPE : SLHP_I_SLICEFRAME_TYPE) : (bInterBSlice ? SLHP_B_SLICEFRAME_TYPE : SLHP_P_SLICEFRAME_TYPE);
3429
3430    SlHParams.First_MB_Address = uiFirst_MB_Address;
3431    SlHParams.Disable_Deblocking_Filter_Idc = (IMG_UINT8) ui8DisableDeblockingFilterIDC;
3432    SlHParams.bPiCInterlace = bIsInterlaced;
3433    SlHParams.iDebAlphaOffsetDiv2 = 0;
3434    SlHParams.iDebBetaOffsetDiv2  = 0;
3435    // setup the new flags used for B frame as reference
3436    SlHParams.bReferencePicture = bInterBSlice ? 0 : 1;
3437    SlHParams.ui16MvcViewIdx = ui16MvcViewIdx;
3438    SlHParams.bIsLongTermRef = bIsLongTermRef;
3439    SlHParams.log2_max_pic_order_cnt = 2;
3440    SlHParams.uLongTermRefNum = 0;
3441    SlHParams.bRefIsLongTermRef[0] = 0;
3442    SlHParams.uRefLongTermRefNum[0] = 0;
3443    SlHParams.bRefIsLongTermRef[1] = 0;
3444    SlHParams.uRefLongTermRefNum[1] = 0;
3445    // Builds a single slice header from the given parameters (mid frame)
3446    // Essential we initialise our header structures before building
3447//    memset(pMTX_Header, 0, 128);
3448    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
3449    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
3450    aui32ElementPointers[0] = This_Element;
3451#ifdef _TOPAZHP_PDUMP_
3452    tng_trace_slice_header_params(&SlHParams);
3453#endif
3454    tng__H264ES_notforsims_writebits_slice_header(pMTX_Header, aui32ElementPointers, &SlHParams, bCabacEnabled, bIsIDR);
3455    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
3456}
3457
3458/**************************************************************************************************
3459* Function:             H263_NOTFORSIMS_PrepareGOBSliceHeader
3460* Description:  Generates the slice params template
3461*
3462***************************************************************************************************/
3463
3464void tng__H263ES_notforsims_prepare_gobsliceheader(
3465    IMG_UINT8       *slice_mem_p)
3466{
3467    // Essential we initialise our header structures before building
3468    SLICE_PARAMS *slice_temp_p = (SLICE_PARAMS*)slice_mem_p;
3469    MTX_HEADER_PARAMS *     pMTX_Header = (MTX_HEADER_PARAMS *) & (slice_temp_p->sSliceHdrTmpl);
3470    MTX_HEADER_ELEMENT *This_Element;
3471    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3472    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
3473    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
3474    aui32ElementPointers[0] = This_Element;
3475    H263_NOTFORSIMS_WriteBits_GOBSliceHeader(pMTX_Header, aui32ElementPointers);
3476    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
3477}
3478
3479/**************************************************************************************************
3480* Function:             MPEG2_PrepareSliceHeader
3481* Description:  Generates the slice params template
3482*
3483***************************************************************************************************/
3484void tng__MPEG2_prepare_sliceheader(
3485    IMG_UINT8               *slice_mem_p)
3486{
3487    // Essential we initialise our header structures before building
3488    SLICE_PARAMS *slice_temp_p = (SLICE_PARAMS*)slice_mem_p;
3489    MTX_HEADER_PARAMS *     pMTX_Header = (MTX_HEADER_PARAMS *) & (slice_temp_p->sSliceHdrTmpl);
3490    MTX_HEADER_ELEMENT *This_Element;
3491    MTX_HEADER_ELEMENT *aui32ElementPointers[MAXNUMBERELEMENTS];
3492    pMTX_Header->ui32Elements = ELEMENTS_EMPTY;
3493    This_Element = (MTX_HEADER_ELEMENT *) pMTX_Header->asElementStream;
3494    aui32ElementPointers[0] = This_Element;
3495//      MPEG2_WriteBits_SliceHeader(pMTX_Header, aui32ElementPointers);
3496    pMTX_Header->ui32Elements++; //Has been used as an index, so need to add 1 for a valid element count
3497}
3498
3499
3500