1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19#include "ti_m4v_config_parser.h"
20#include "oscl_mem.h"
21#include "oscl_dll.h"
22OSCL_DLL_ENTRY_POINT_DEFAULT()
23
24#define PV_CLZ(A,B) while (((B) & 0x8000) == 0) {(B) <<=1; A++;}
25
26static const uint32 mask[33] =
27{
28    0x00000000, 0x00000001, 0x00000003, 0x00000007,
29    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
30    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
31    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
32    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
33    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
34    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
35    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
36    0xffffffff
37};
38
39int32 LocateFrameHeader(uint8 *ptr, int32 size)
40{
41    int32 count = 0;
42    int32 i = size;
43
44    if (size < 1)
45    {
46        return 0;
47    }
48    while (i--)
49    {
50        if ((count > 1) && (*ptr == 0x01))
51        {
52            i += 2;
53            break;
54        }
55
56        if (*ptr++)
57            count = 0;
58        else
59            count++;
60    }
61    return (size - (i + 1));
62}
63
64void movePointerTo(mp4StreamType *psBits, int32 pos)
65{
66    uint32 byte_pos;
67    if (pos < 0)
68    {
69        pos = 0;
70    }
71
72    byte_pos = pos >> 3;
73
74    if (byte_pos > (psBits->numBytes - psBits->bytePos))
75    {
76        byte_pos = (psBits->numBytes - psBits->bytePos);
77    }
78
79    psBits->bytePos = byte_pos & -4;
80    psBits->dataBitPos = psBits->bytePos << 3;
81    FlushBits(psBits, ((pos & 0x7) + ((byte_pos & 0x3) << 3)));
82}
83
84int16 SearchNextM4VFrame(mp4StreamType *psBits)
85{
86    int16 status = 0;
87    uint8 *ptr;
88    int32 i;
89    uint32 initial_byte_aligned_position = (psBits->dataBitPos + 7) >> 3;
90
91    ptr = psBits->data + initial_byte_aligned_position;
92
93    i = LocateFrameHeader(ptr, psBits->numBytes - initial_byte_aligned_position);
94    if (psBits->numBytes <= initial_byte_aligned_position + i)
95    {
96        status = -1;
97    }
98    (void)movePointerTo(psBits, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */
99    return status;
100}
101
102OSCL_EXPORT_REF int16 iGetM4VConfigInfo(uint8 *buffer, int32 length, int32 *width, int32 *height, int32 *display_width, int32 *display_height)
103{
104    int16 status;
105    mp4StreamType psBits;
106    psBits.data = buffer;
107    psBits.numBytes = length;
108    psBits.bitBuf = 0;
109    psBits.bitPos = 32;
110    psBits.bytePos = 0;
111    psBits.dataBitPos = 0;
112    *width = *height = *display_height = *display_width = 0;
113
114    if (length == 0)
115    {
116        return MP4_INVALID_VOL_PARAM;
117    }
118    int32 profilelevel = 0; // dummy value discarded here
119    status = iDecodeVOLHeader(&psBits, width, height, display_width, display_height, &profilelevel);
120    return status;
121}
122
123// name: iDecodeVOLHeader
124// Purpose: decode VOL header
125// return:  error code
126OSCL_EXPORT_REF int16 iDecodeVOLHeader(mp4StreamType *psBits, int32 *width, int32 *height, int32 *display_width, int32 *display_height, int32 *profilelevel)
127{
128    int16 iErrorStat;
129    uint32 codeword;
130    int32 time_increment_resolution, nbits_time_increment;
131    int32 i, j;
132
133    *profilelevel = 0x0000FFFF; // init to some invalid value. When this value is returned, then no profilelevel info is available
134
135    ShowBits(psBits, 32, &codeword);
136
137    if (codeword == VISUAL_OBJECT_SEQUENCE_START_CODE)
138    {
139        //DV: this is the wrong way to skip bits, use FLush or Read psBits->dataBitPos += 32;
140        ReadBits(psBits, 32, &codeword); // skip 32 bits of the Start code
141
142        ReadBits(psBits, 8, &codeword);
143
144        // record profile and level
145        *profilelevel = (int) codeword;
146
147        ShowBits(psBits, 32, &codeword);
148        if (codeword == USER_DATA_START_CODE)
149        {
150            iErrorStat = DecodeUserData(psBits);
151            if (iErrorStat) return MP4_INVALID_VOL_PARAM;
152        }
153
154
155        ReadBits(psBits, 32, &codeword);
156        if (codeword != VISUAL_OBJECT_START_CODE) return MP4_INVALID_VOL_PARAM;
157
158        /*  is_visual_object_identifier            */
159        ReadBits(psBits, 1, &codeword);
160
161        if (codeword)
162        {
163            /* visual_object_verid                            */
164            ReadBits(psBits, 4, &codeword);
165            /* visual_object_priority                         */
166            ReadBits(psBits, 3, &codeword);
167        }
168        /* visual_object_type                                 */
169        ReadBits(psBits, 4, &codeword);
170
171        if (codeword == 1)
172        { /* video_signal_type */
173            ReadBits(psBits, 1, &codeword);
174            if (codeword == 1)
175            {
176                /* video_format */
177                ReadBits(psBits, 3, &codeword);
178                /* video_range  */
179                ReadBits(psBits, 1, &codeword);
180                /* color_description */
181                ReadBits(psBits, 1, &codeword);
182                if (codeword == 1)
183                {
184                    /* color_primaries */
185                    ReadBits(psBits, 8, &codeword);;
186                    /* transfer_characteristics */
187                    ReadBits(psBits, 8, &codeword);
188                    /* matrix_coefficients */
189                    ReadBits(psBits, 8, &codeword);
190                }
191            }
192        }
193        else
194        {
195            int16 status = 0;
196            do
197            {
198                /* Search for VOL_HEADER */
199                status = SearchNextM4VFrame(psBits); /* search 0x00 0x00 0x01 */
200                if (status != 0)
201                    return MP4_INVALID_VOL_PARAM;
202
203                status = ReadBits(psBits, VOL_START_CODE_LENGTH, &codeword);
204            }
205            while ((codeword != VOL_START_CODE) && (status == 0));
206            goto decode_vol;
207        }
208        /* next_start_code() */
209        ByteAlign(psBits);
210
211        ShowBits(psBits, 32, &codeword);
212        if (codeword == USER_DATA_START_CODE)
213        {
214            iErrorStat = DecodeUserData(psBits);
215            if (iErrorStat) return MP4_INVALID_VOL_PARAM;
216        }
217        ShowBits(psBits, 27, &codeword);
218    }
219    else
220    {
221        ShowBits(psBits, 27, &codeword);
222    }
223
224    if (codeword == VO_START_CODE)
225    {
226
227        ReadBits(psBits, 32, &codeword);
228
229        /* video_object_layer_start_code                   */
230        ReadBits(psBits, 28, &codeword);
231        if (codeword != VOL_START_CODE)
232        {
233            if (psBits->dataBitPos >= (psBits->numBytes << 3))
234            {
235                return SHORT_HEADER_MODE; /* SH */
236            }
237            else
238            {
239                int16 status = 0;
240                do
241                {
242                    /* Search for VOL_HEADER */
243                    status = SearchNextM4VFrame(psBits); /* search 0x00 0x00 0x01 */
244                    if (status != 0)
245                        return MP4_INVALID_VOL_PARAM;
246
247                    status = ReadBits(psBits, VOL_START_CODE_LENGTH, &codeword);
248                }
249                while ((codeword != VOL_START_CODE) && (status == 0));
250                goto decode_vol;
251            }
252        }
253decode_vol:
254
255        uint32 vol_id;
256
257        /* vol_id (4 bits) */
258        ReadBits(psBits, 4, & vol_id);
259
260        // RandomAccessibleVOLFlag
261        ReadBits(psBits, 1, &codeword);
262
263        //Video Object Type Indication
264        ReadBits(psBits, 8, &codeword);
265        if (codeword != 1)
266        {
267            //return MP4_INVALID_VOL_PARAM; //TI supports this feature
268        }
269
270        // is_object_layer_identifier
271        ReadBits(psBits, 1, &codeword);
272
273        if (codeword)
274        {
275            ReadBits(psBits, 4, &codeword);
276            ReadBits(psBits, 3, &codeword);
277        }
278
279        // aspect ratio
280        ReadBits(psBits, 4, &codeword);
281
282        if (codeword == 0xF)
283        {
284            // Extended Parameter
285            /* width */
286            ReadBits(psBits, 8, &codeword);
287            /* height */
288            ReadBits(psBits, 8, &codeword);
289        }
290
291        ReadBits(psBits, 1, &codeword);
292
293        if (codeword)
294        {
295            ReadBits(psBits, 2, &codeword);
296            if (codeword != 1)
297            {
298                return MP4_INVALID_VOL_PARAM;
299            }
300
301            ReadBits(psBits, 1, &codeword);
302
303            if (!codeword)
304            {
305                //return MP4_INVALID_VOL_PARAM; //TI supports this feature
306            }
307
308            ReadBits(psBits, 1, &codeword);
309            if (codeword)   /* if (vbv_parameters) {}, page 36 */
310            {
311                ReadBits(psBits, 15, &codeword);
312                ReadBits(psBits, 1, &codeword);
313                if (codeword != 1)
314                {
315                    return MP4_INVALID_VOL_PARAM;
316                }
317
318                ReadBits(psBits, 15, &codeword);
319                ReadBits(psBits, 1, &codeword);
320                if (codeword != 1)
321                {
322                    return MP4_INVALID_VOL_PARAM;
323                }
324
325
326                ReadBits(psBits, 19, &codeword);
327                if (!(codeword & 0x8))
328                {
329                    return MP4_INVALID_VOL_PARAM;
330                }
331
332                ReadBits(psBits, 11, &codeword);
333                ReadBits(psBits, 1, &codeword);
334                if (codeword != 1)
335                {
336                    return MP4_INVALID_VOL_PARAM;
337                }
338
339                ReadBits(psBits, 15, &codeword);
340                ReadBits(psBits, 1, &codeword);
341                if (codeword != 1)
342                {
343                    return MP4_INVALID_VOL_PARAM;
344                }
345            }
346
347        }
348
349        ReadBits(psBits, 2, &codeword);
350
351        if (codeword != 0)
352        {
353            return MP4_INVALID_VOL_PARAM;
354        }
355
356        ReadBits(psBits, 1, &codeword);
357        if (codeword != 1)
358        {
359            return MP4_INVALID_VOL_PARAM;
360        }
361
362        ReadBits(psBits, 16, &codeword);
363        time_increment_resolution = codeword;
364
365
366        ReadBits(psBits, 1, &codeword);
367        if (codeword != 1)
368        {
369            return MP4_INVALID_VOL_PARAM;
370        }
371
372
373
374        ReadBits(psBits, 1, &codeword);
375
376        if (codeword && time_increment_resolution > 2)
377        {
378            i = time_increment_resolution - 1;
379            j = 1;
380            while (i >>= 1)
381            {
382                j++;
383            }
384            nbits_time_increment = j;
385
386            ReadBits(psBits, nbits_time_increment, &codeword);
387        }
388
389        ReadBits(psBits, 1, &codeword);
390        if (codeword != 1)
391        {
392            return MP4_INVALID_VOL_PARAM;
393        }
394
395        /* this should be 176 for QCIF */
396        ReadBits(psBits, 13, &codeword);
397        *display_width = (int32)codeword;
398        ReadBits(psBits, 1, &codeword);
399        if (codeword != 1)
400        {
401            return MP4_INVALID_VOL_PARAM;
402        }
403
404        /* this should be 144 for QCIF */
405        ReadBits(psBits, 13, &codeword);
406        *display_height = (int32)codeword;
407
408        *width = (*display_width + 15) & -16;
409        *height = (*display_height + 15) & -16;
410    }
411    else
412    {
413        /* SHORT_HEADER */
414        ShowBits(psBits, SHORT_VIDEO_START_MARKER_LENGTH, &codeword);
415        if (codeword == SHORT_VIDEO_START_MARKER)
416        {
417            iDecodeShortHeader(psBits, width, height, display_width, display_height);
418        }
419        else
420        {
421            int16 status = 0;
422            do
423            {
424                /* Search for VOL_HEADER */
425                status = SearchNextM4VFrame(psBits); /* search 0x00 0x00 0x01 */
426                if (status != 0)
427                {
428                    return MP4_INVALID_VOL_PARAM;
429                }
430
431                status = ReadBits(psBits, VOL_START_CODE_LENGTH, &codeword);
432            }
433            while ((codeword != VOL_START_CODE) && (status == 0));
434            goto decode_vol;
435        }
436    }
437    return 0;
438}
439
440
441
442OSCL_EXPORT_REF
443int16 iDecodeShortHeader(mp4StreamType *psBits,
444                         int32 *width,
445                         int32 *height,
446                         int32 *display_width,
447                         int32 *display_height)
448{
449    uint32 codeword;
450    int32	extended_PTYPE = 0;
451    int32 UFEP = 0;
452    int32 custom_PFMT = 0;
453
454    ShowBits(psBits, 22, &codeword);
455
456    if (codeword !=  0x20)
457    {
458        return MP4_INVALID_VOL_PARAM;
459    }
460    FlushBits(psBits, 22);
461    ReadBits(psBits, 8, &codeword);
462
463    ReadBits(psBits, 1, &codeword);
464    if (codeword == 0) return MP4_INVALID_VOL_PARAM;
465
466    ReadBits(psBits, 1, &codeword);
467    if (codeword == 1) return MP4_INVALID_VOL_PARAM;
468
469    ReadBits(psBits, 1, &codeword);
470    if (codeword == 1) return MP4_INVALID_VOL_PARAM;
471
472    ReadBits(psBits, 1, &codeword);
473    if (codeword == 1) return MP4_INVALID_VOL_PARAM;
474
475    ReadBits(psBits, 1, &codeword);
476    if (codeword == 1) return MP4_INVALID_VOL_PARAM;
477
478    /* source format */
479    ReadBits(psBits, 3, &codeword);
480    switch (codeword)
481    {
482        case 1:
483            *width = 128;
484            *height = 96;
485            break;
486
487        case 2:
488            *width = 176;
489            *height = 144;
490            break;
491
492        case 3:
493            *width = 352;
494            *height = 288;
495            break;
496
497        case 4:
498            *width = 704;
499            *height = 576;
500            break;
501
502        case 5:
503            *width = 1408;
504            *height = 1152;
505            break;
506
507        case 7:
508            extended_PTYPE = 1;
509            break;
510        default:
511            /* Msg("H.263 source format not legal\n"); */
512            return MP4_INVALID_VOL_PARAM;
513    }
514
515    if (extended_PTYPE == 0)
516    {
517        *display_width = *width;
518        *display_height = *height;
519        return 0;
520    }
521    /* source format */
522    ReadBits(psBits, 3, &codeword);
523    UFEP = codeword;
524    if (UFEP == 1)
525    {
526        ReadBits(psBits, 3, &codeword);
527        switch (codeword)
528        {
529            case 1:
530                *width = 128;
531                *height = 96;
532                break;
533
534            case 2:
535                *width = 176;
536                *height = 144;
537                break;
538
539            case 3:
540                *width = 352;
541                *height = 288;
542                break;
543
544            case 4:
545                *width = 704;
546                *height = 576;
547                break;
548
549            case 5:
550                *width = 1408;
551                *height = 1152;
552                break;
553
554            case 6:
555                custom_PFMT = 1;
556                break;
557            default:
558                /* Msg("H.263 source format not legal\n"); */
559                return MP4_INVALID_VOL_PARAM;
560        }
561        if (custom_PFMT == 0)
562        {
563            *display_width = *width;
564            *display_height = *height;
565            return 0;
566        }
567        ReadBits(psBits, 1, &codeword);
568        ReadBits(psBits, 1, &codeword);
569        if (codeword) return MP4_INVALID_VOL_PARAM;
570        ReadBits(psBits, 1, &codeword);
571        if (codeword) return MP4_INVALID_VOL_PARAM;
572        ReadBits(psBits, 1, &codeword);
573        if (codeword) return MP4_INVALID_VOL_PARAM;
574        ReadBits(psBits, 3, &codeword);
575        ReadBits(psBits, 3, &codeword);
576        if (codeword) return MP4_INVALID_VOL_PARAM; 			/* RPS, ISD, AIV */
577        ReadBits(psBits, 1, &codeword);
578        ReadBits(psBits, 4, &codeword);
579        if (codeword != 8) return MP4_INVALID_VOL_PARAM;
580    }
581    if (UFEP == 0 || UFEP == 1)
582    {
583        ReadBits(psBits, 3, &codeword);
584        if (codeword > 1) return MP4_INVALID_VOL_PARAM;
585        ReadBits(psBits, 1, &codeword);
586        if (codeword) return MP4_INVALID_VOL_PARAM;
587        ReadBits(psBits, 1, &codeword);
588        if (codeword) return MP4_INVALID_VOL_PARAM;
589        ReadBits(psBits, 1, &codeword);
590        ReadBits(psBits, 3, &codeword);
591        if (codeword != 1) return MP4_INVALID_VOL_PARAM;
592    }
593    else
594    {
595        return MP4_INVALID_VOL_PARAM;
596    }
597    ReadBits(psBits, 1, &codeword);
598    if (codeword) return MP4_INVALID_VOL_PARAM; /* CPM */
599    if (custom_PFMT == 1 && UFEP == 1)
600    {
601        ReadBits(psBits, 4, &codeword);
602        if (codeword == 0) return MP4_INVALID_VOL_PARAM;
603        if (codeword == 0xf)
604        {
605            ReadBits(psBits, 8, &codeword);
606            ReadBits(psBits, 8, &codeword);
607        }
608        ReadBits(psBits, 9, &codeword);
609        *display_width = (codeword + 1) << 2;
610        *width = (*display_width + 15) & -16;
611        ReadBits(psBits, 1, &codeword);
612        if (codeword != 1) return MP4_INVALID_VOL_PARAM;
613        ReadBits(psBits, 9, &codeword);
614        if (codeword == 0) return MP4_INVALID_VOL_PARAM;
615        *display_height = codeword << 2;
616        *height = (*display_height + 15) & -16;
617    }
618
619    return 0;
620}
621
622
623int16 ShowBits(
624    mp4StreamType *pStream,           /* Input Stream */
625    uint8 ucNBits,          /* nr of bits to read */
626    uint32 *pulOutData      /* output target */
627)
628{
629    uint8 *bits;
630    uint32 dataBitPos = pStream->dataBitPos;
631    uint32 bitPos = pStream->bitPos;
632    uint32 dataBytePos;
633
634    uint i;
635
636    if (ucNBits > (32 - bitPos))    /* not enough bits */
637    {
638        dataBytePos = dataBitPos >> 3; /* Byte Aligned Position */
639        bitPos = dataBitPos & 7; /* update bit position */
640        if (dataBytePos > pStream->numBytes - 4)
641        {
642            pStream->bitBuf = 0;
643            for (i = 0;i < pStream->numBytes - dataBytePos;i++)
644            {
645                pStream->bitBuf |= pStream->data[dataBytePos+i];
646                pStream->bitBuf <<= 8;
647            }
648            pStream->bitBuf <<= 8 * (3 - i);
649        }
650        else
651        {
652            bits = &pStream->data[dataBytePos];
653            pStream->bitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
654        }
655        pStream->bitPos = bitPos;
656    }
657
658    bitPos += ucNBits;
659
660    *pulOutData = (pStream->bitBuf >> (32 - bitPos)) & mask[(uint16)ucNBits];
661
662
663    return 0;
664}
665
666int16 FlushBits(
667    mp4StreamType *pStream,           /* Input Stream */
668    uint8 ucNBits                      /* number of bits to flush */
669)
670{
671    uint8 *bits;
672    uint32 dataBitPos = pStream->dataBitPos;
673    uint32 bitPos = pStream->bitPos;
674    uint32 dataBytePos;
675
676
677    if ((dataBitPos + ucNBits) > (uint32)(pStream->numBytes << 3))
678        return (-2); // Buffer over run
679
680    dataBitPos += ucNBits;
681    bitPos     += ucNBits;
682
683    if (bitPos > 32)
684    {
685        dataBytePos = dataBitPos >> 3;    /* Byte Aligned Position */
686        bitPos = dataBitPos & 7; /* update bit position */
687        bits = &pStream->data[dataBytePos];
688        pStream->bitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
689    }
690
691    pStream->dataBitPos = dataBitPos;
692    pStream->bitPos     = bitPos;
693
694    return 0;
695}
696
697int16 ReadBits(
698    mp4StreamType *pStream,           /* Input Stream */
699    uint8 ucNBits,                     /* nr of bits to read */
700    uint32 *pulOutData                 /* output target */
701)
702{
703    uint8 *bits;
704    uint32 dataBitPos = pStream->dataBitPos;
705    uint32 bitPos = pStream->bitPos;
706    uint32 dataBytePos;
707
708
709    if ((dataBitPos + ucNBits) > (pStream->numBytes << 3))
710    {
711        *pulOutData = 0;
712        return (-2); // Buffer over run
713    }
714
715    //  dataBitPos += ucNBits;
716
717    if (ucNBits > (32 - bitPos))    /* not enough bits */
718    {
719        dataBytePos = dataBitPos >> 3;    /* Byte Aligned Position */
720        bitPos = dataBitPos & 7; /* update bit position */
721        bits = &pStream->data[dataBytePos];
722        pStream->bitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
723    }
724
725    pStream->dataBitPos += ucNBits;
726    pStream->bitPos      = (unsigned char)(bitPos + ucNBits);
727
728    *pulOutData = (pStream->bitBuf >> (32 - pStream->bitPos)) & mask[(uint16)ucNBits];
729
730    return 0;
731}
732
733
734
735int16 ByteAlign(
736    mp4StreamType *pStream           /* Input Stream */
737)
738{
739    uint8 *bits;
740    uint32 dataBitPos = pStream->dataBitPos;
741    uint32 bitPos = pStream->bitPos;
742    uint32 dataBytePos;
743    uint32 leftBits;
744
745    leftBits =  8 - (dataBitPos & 0x7);
746    if (leftBits == 8)
747    {
748        if ((dataBitPos + 8) > (uint32)(pStream->numBytes << 3))
749            return (-2); // Buffer over run
750        dataBitPos += 8;
751        bitPos += 8;
752    }
753    else
754    {
755        dataBytePos = dataBitPos >> 3;
756        dataBitPos += leftBits;
757        bitPos += leftBits;
758    }
759
760
761    if (bitPos > 32)
762    {
763        dataBytePos = dataBitPos >> 3;    /* Byte Aligned Position */
764        bits = &pStream->data[dataBytePos];
765        pStream->bitBuf = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
766    }
767
768    pStream->dataBitPos = dataBitPos;
769    pStream->bitPos     = bitPos;
770
771    return 0;
772}
773
774int16 DecodeUserData(mp4StreamType *pStream)
775{
776
777    uint32 codeword;
778    int16 iErrorStat;
779
780    iErrorStat = ReadBits(pStream, 32, &codeword);
781    if (iErrorStat) return iErrorStat;
782    iErrorStat = ShowBits(pStream, 24, &codeword);
783    if (iErrorStat) return iErrorStat;
784
785    while (codeword != 1)
786    {
787        /* Discard user data for now. */
788        iErrorStat = ReadBits(pStream, 8, &codeword);
789        if (iErrorStat) return iErrorStat;
790        iErrorStat = ShowBits(pStream, 24, &codeword);
791        if (iErrorStat) return iErrorStat;
792    }
793    return 0;
794}
795
796
797OSCL_EXPORT_REF int16 iGetAVCConfigInfo(uint8 *buffer, int32 length, int32 *width, int32 *height, int32 *display_width, int32 *display_height, int32 *profile_idc, int32 *level_idc, uint32 *entropy_coding_mode_flag)
798{
799    int16 status;
800    mp4StreamType psBits;
801    uint16 sps_length, pps_length;
802    int32 size;
803    int32 i = 0;
804    uint8* sps = NULL;
805    uint8* temp = (uint8 *)OSCL_MALLOC(sizeof(uint8) * length);
806    uint8* pps = NULL;
807
808
809    if (temp)
810    {
811        sps = temp; // Make a copy of the original pointer to be freed later
812        // Successfull allocation... copy input buffer
813        oscl_memcpy(sps, buffer, length);
814    }
815    else
816    {
817        // Allocation failed
818        return MP4_INVALID_VOL_PARAM;
819    }
820
821    if (length < 3)
822    {
823        OSCL_FREE(temp);
824        return MP4_INVALID_VOL_PARAM;
825    }
826
827    *width = *height = *display_height = *display_width = 0;
828
829    if (sps[0] == 0 && sps[1] == 0)
830    {
831        /* find SC at the beginning of the NAL */
832        while (sps[i++] == 0 && i < length)
833        {
834        }
835
836        if (sps[i-1] == 1)
837        {
838            sps += i;
839
840            sps_length = 0;
841            // search for the next start code
842            while (!(sps[sps_length] == 0 && sps[sps_length+1] == 0 && sps[sps_length+2] == 1) &&
843                    sps_length < length - i - 2)
844            {
845                sps_length++;
846            }
847
848            if (sps_length >= length - i - 2)
849            {
850                OSCL_FREE(temp);
851                return MP4_INVALID_VOL_PARAM;
852            }
853
854            pps_length = length - i - sps_length - 3;
855            pps = sps + sps_length + 3;
856        }
857        else
858        {
859            OSCL_FREE(temp);
860            return MP4_INVALID_VOL_PARAM;
861        }
862    }
863    else
864    {
865        sps_length = (uint16)(sps[1] << 8) | sps[0];
866        sps += 2;
867        pps = sps + sps_length;
868        pps_length = (uint16)(pps[1] << 8) | pps[0];
869        pps += 2;
870    }
871
872    if (sps_length + pps_length > length)
873    {
874        OSCL_FREE(temp);
875        return MP4_INVALID_VOL_PARAM;
876    }
877
878    size = sps_length;
879
880    Parser_EBSPtoRBSP(sps, &size);
881
882    psBits.data = sps;
883    psBits.numBytes = size;
884    psBits.bitBuf = 0;
885    psBits.bitPos = 32;
886    psBits.bytePos = 0;
887    psBits.dataBitPos = 0;
888
889    if (DecodeSPS(&psBits, width, height, display_width, display_height, profile_idc, level_idc))
890    {
891        OSCL_FREE(temp);
892        return MP4_INVALID_VOL_PARAM;
893    }
894
895    // now do PPS
896    size = pps_length;
897
898    Parser_EBSPtoRBSP(pps, &size);
899    psBits.data = pps;
900    psBits.numBytes = size;
901    psBits.bitBuf = 0;
902    psBits.bitPos = 32;
903    psBits.bytePos = 0;
904    psBits.dataBitPos = 0;
905
906    status = DecodePPS(&psBits, entropy_coding_mode_flag);
907
908    OSCL_FREE(temp);
909
910    return status;
911}
912
913void scaling_list_h264(int32 i4_list_size, mp4StreamType *psBits)
914{
915    int32 i4_j, i4_delta_scale, i4_lastScale = 8, i4_nextScale =8;
916
917
918    for(i4_j = 0; i4_j < i4_list_size; i4_j++)
919    {
920        if(i4_nextScale !=0)
921        {
922             se_v(psBits, &i4_delta_scale);
923            i4_nextScale = ((i4_lastScale + i4_delta_scale + 256) & 0xff);
924
925        }
926        i4_lastScale  = (i4_nextScale == 0)? (i4_lastScale) : (i4_nextScale);
927    }
928}
929
930int16 DecodeSPS(mp4StreamType *psBits, int32 *width, int32 *height, int32 *display_width, int32 *display_height, int32 *profile_idc, int32 *level_idc)
931{
932    uint32 temp;
933    int32 temp0;
934    uint left_offset, right_offset, top_offset, bottom_offset;
935    uint i;
936    c_bool highProfileDetected = false;
937
938    ReadBits(psBits, 8, &temp);
939
940    if ((temp & 0x1F) != 7) return MP4_INVALID_VOL_PARAM;
941
942    ReadBits(psBits, 8, &temp);
943
944    *profile_idc = temp;
945
946    ReadBits(psBits, 1, &temp);
947    ReadBits(psBits, 1, &temp);
948    ReadBits(psBits, 1, &temp);
949    ReadBits(psBits, 5, &temp);
950    ReadBits(psBits, 8, &temp);
951
952    *level_idc = temp;
953
954    if (temp > 51)
955        return MP4_INVALID_VOL_PARAM;
956
957    ue_v(psBits, &temp);
958
959    if(*profile_idc == H264_PROFILE_IDC_HIGH)
960    {
961        /* High Profile detected; additional parameters to be parsed */
962        uint32 i4_chroma_format_idc, i4_bit_depth_luma_minus8, i4_bit_depth_chroma_minus8;
963        uint32 i4_seq_scaling_matrix_present_flag, i4_qpprime_y_zero_transform_bypass_flag;
964
965        highProfileDetected = true;
966
967        /* reading chroma_format_idc   */
968        ue_v(psBits, &i4_chroma_format_idc);
969
970        if(i4_chroma_format_idc != 1 )
971        {
972            /* chroma_format_idc 1 represents 420. Other possibility is monochrome, not supported currently */
973            return (-1);
974        }
975
976        /* reading bit_depth_luma_minus8   */
977        ue_v(psBits, &i4_bit_depth_luma_minus8);
978
979        if(i4_bit_depth_luma_minus8 != 0)
980        {
981            /* only 8 bit supported, higher bit depth not supported */
982            return (-1);
983        }
984
985        /* reading bit_depth_chroma_minus8   */
986        ue_v(psBits, &i4_bit_depth_chroma_minus8);
987
988        if(i4_bit_depth_chroma_minus8 != 0)
989        {
990            /* only 8 bit supported, higher bit depth not supported */
991            return (-1);
992        }
993
994        /* reading qpprime_y_zero_transform_bypass_flag   */
995        ReadBits(psBits, 1, &i4_qpprime_y_zero_transform_bypass_flag);
996        if(i4_qpprime_y_zero_transform_bypass_flag != 0)
997        {
998            return (-1);
999        }
1000
1001        /* reading seq_scaling_matrix_present_flag   */
1002        ReadBits(psBits, 1, &i4_seq_scaling_matrix_present_flag);
1003
1004        if(i4_seq_scaling_matrix_present_flag)
1005        {
1006            int32 i4_i;
1007            for(i4_i =0; i4_i < 8; i4_i++)
1008            {
1009                uint32 i4_scaling_list_present;
1010                ReadBits(psBits, 1, &i4_scaling_list_present);
1011
1012                if(i4_scaling_list_present)
1013                {
1014                    if(i4_i < 6)
1015                    {
1016                        scaling_list_h264(16, psBits);
1017                    }
1018                    else
1019                    {
1020                        scaling_list_h264(64, psBits);
1021                    }
1022                }
1023            }
1024        }
1025    }
1026
1027    ue_v(psBits, &temp);
1028    ue_v(psBits, &temp);
1029
1030    if (temp == 0)
1031    {
1032        ue_v(psBits, &temp);
1033    }
1034    else if (temp == 1)
1035    {
1036        ReadBits(psBits, 1, &temp);
1037        se_v(psBits, &temp0);
1038        se_v(psBits, &temp0);
1039        ue_v(psBits, &temp);
1040
1041        for (i = 0; i < temp; i++)
1042        {
1043            se_v(psBits, &temp0);
1044        }
1045    }
1046    ue_v(psBits, &temp);
1047
1048
1049    ReadBits(psBits, 1, &temp);
1050    ue_v(psBits, &temp);
1051    *display_width = *width = (temp + 1) << 4;
1052    ue_v(psBits, &temp);
1053    *display_height = *height = (temp + 1) << 4;
1054
1055    ReadBits(psBits, 1, &temp);
1056    if (!temp)
1057    {
1058        // we do not support if frame_mb_only_flag is off
1059        return MP4_INVALID_VOL_PARAM;
1060        //ReadBits(psBits,1, &temp);
1061    }
1062
1063    ReadBits(psBits, 1, &temp);
1064
1065    ReadBits(psBits, 1, &temp);
1066
1067    if (temp)
1068    {
1069        ue_v(psBits, (uint32*)&left_offset);
1070        ue_v(psBits, (uint32*)&right_offset);
1071        ue_v(psBits, (uint32*)&top_offset);
1072        ue_v(psBits, (uint32*)&bottom_offset);
1073
1074        *display_width = *width - 2 * (right_offset + left_offset);
1075        *display_height = *height - 2 * (top_offset + bottom_offset);
1076    }
1077
1078    /*	no need to check further */
1079#if USE_LATER
1080    ReadBits(psBits, 1, &temp);
1081    if (temp)
1082    {
1083        if (!DecodeVUI(psBits))
1084        {
1085            return MP4_INVALID_VOL_PARAM;
1086        }
1087    }
1088#endif
1089    return 0; // return 0 for success
1090}
1091
1092#if USE_LATER
1093/* unused for now */
1094int32 DecodeVUI(mp4StreamType *psBits)
1095{
1096    uint temp;
1097    uint32 temp32;
1098    uint aspect_ratio_idc, overscan_appopriate_flag, video_format, video_full_range_flag;
1099    int32 status;
1100
1101    ReadBits(psBits, 1, &temp); /* aspect_ratio_info_present_flag */
1102    if (temp)
1103    {
1104        ReadBits(psBits, 8, &aspect_ratio_idc);
1105        if (aspect_ratio_idc == 255)
1106        {
1107            ReadBits(psBits, 16, &temp); /* sar_width */
1108            ReadBits(psBits, 16, &temp); /* sar_height */
1109        }
1110    }
1111    ReadBits(psBits, 1, &temp); /* overscan_info_present */
1112    if (temp)
1113    {
1114        ReadBits(psBits, 1, &overscan_appopriate_flag);
1115    }
1116    ReadBits(psBits, 1, &temp); /* video_signal_type_present_flag */
1117    if (temp)
1118    {
1119        ReadBits(psBits, 3, &video_format);
1120        ReadBits(psBits, 1, &video_full_range_flag);
1121        ReadBits(psBits, 1, &temp); /* colour_description_present_flag */
1122        if (temp)
1123        {
1124            ReadBits(psBits, 8, &temp); /* colour_primaries */
1125            ReadBits(psBits, 8, &temp); /* transfer_characteristics */
1126            ReadBits(psBits, 8, &temp); /* matrix coefficients */
1127        }
1128    }
1129    ReadBits(psBits, 1, &temp);/*	chroma_loc_info_present_flag */
1130    if (temp)
1131    {
1132        ue_v(psBits, &temp); /*  chroma_sample_loc_type_top_field */
1133        ue_v(psBits, &temp); /*  chroma_sample_loc_type_bottom_field */
1134    }
1135
1136    ReadBits(psBits, 1, &temp); /*	timing_info_present_flag*/
1137    if (temp)
1138    {
1139        ReadBits(psBits, 32, &temp32); /*  num_unit_in_tick*/
1140        ReadBits(psBits, 32, &temp32); /*	time_scale */
1141        ReadBits(psBits, 1, &temp); /*	fixed_frame_rate_flag */
1142    }
1143
1144    ReadBits(psBits, 1, &temp); /*	nal_hrd_parameters_present_flag */
1145    if (temp)
1146    {
1147        if (!DecodeHRD(psBits))
1148        {
1149            return 1;
1150        }
1151    }
1152    ReadBits(psBits, 1, &temp32); /*	vcl_hrd_parameters_present_flag*/
1153    if (temp32)
1154    {
1155        if (!DecodeHRD(psBits))
1156        {
1157            return 1;
1158        }
1159    }
1160    if (temp || temp32)
1161    {
1162        ReadBits(psBits, 1, &temp);		/*	low_delay_hrd_flag */
1163    }
1164    ReadBits(psBits, 1, &temp); /*	pic_struct_present_flag */
1165    status = ReadBits(psBits, 1, &temp); /*	_restriction_flag */
1166    if (status != 0) // buffer overrun
1167    {
1168        return 1;
1169    }
1170
1171    if (temp)
1172    {
1173        ReadBits(psBits, 1, &temp); /*	motion_vectors_over_pic_boundaries_flag */
1174        ue_v(psBits, &temp); /*	max_bytes_per_pic_denom */
1175        ue_v(psBits, &temp); /*	max_bits_per_mb_denom */
1176        ue_v(psBits, &temp); /*	log2_max_mv_length_horizontal */
1177        ue_v(psBits, &temp); /*	log2_max_mv_length_vertical */
1178        ue_v(psBits, &temp); /*	num_reorder_frames */
1179        ue_v(psBits, &temp); /*	max_dec_frame_buffering */
1180    }
1181
1182    return 0; // 0 for success
1183}
1184
1185/* unused for now */
1186int32 DecodeHRD(mp4StreamType *psBits)
1187{
1188    uint temp;
1189    uint cpb_cnt_minus1;
1190    uint i;
1191    int32 status;
1192
1193    ue_v(psBits, &cpb_cnt_minus1);
1194    ReadBits(psBits, 4, &temp); /*	bit_rate_scale */
1195    ReadBits(psBits, 4, &temp); /*	cpb_size_scale */
1196    for (i = 0; i <= cpb_cnt_minus1; i++)
1197    {
1198        ue_v(psBits, &temp); /*	bit_rate_value_minus1[i] */
1199        ue_v(psBits, &temp); /*	cpb_size_value_minus1[i] */
1200        ue_v(psBits, &temp); /*	cbr_flag[i] */
1201    }
1202    ReadBits(psBits, 5, &temp); /*	initial_cpb_removal_delay_length_minus1 */
1203    ReadBits(psBits, 5, &temp); /*	cpb_removal_delay_length_minus1 */
1204    ReadBits(psBits, 5, &temp); /*	dpb_output_delay_length_minus1 */
1205    status = ReadBits(psBits, 5, &temp); /*	time_offset_length	*/
1206
1207    if (status != 0) // buffer overrun
1208    {
1209        return 1;
1210    }
1211
1212    return 0; // 0 for success
1213}
1214#endif
1215
1216// only check for entropy coding mode
1217int32 DecodePPS(mp4StreamType *psBits, uint32 *entropy_coding_mode_flag)
1218{
1219    uint32 temp, pic_parameter_set_id, seq_parameter_set_id;
1220
1221    ReadBits(psBits, 8, &temp);
1222
1223    if ((temp & 0x1F) != 8) return MP4_INVALID_VOL_PARAM;
1224
1225    ue_v(psBits, &pic_parameter_set_id);
1226    ue_v(psBits, &seq_parameter_set_id);
1227
1228    ReadBits(psBits, 1, entropy_coding_mode_flag);
1229
1230    return 0;
1231}
1232
1233void ue_v(mp4StreamType *psBits, uint32 *codeNum)
1234{
1235    uint32 temp;
1236    uint tmp_cnt;
1237    int32 leading_zeros = 0;
1238    ShowBits(psBits, 16, &temp);
1239    tmp_cnt = temp  | 0x1;
1240
1241    PV_CLZ(leading_zeros, tmp_cnt)
1242
1243    if (leading_zeros < 8)
1244    {
1245        *codeNum = (temp >> (15 - (leading_zeros << 1))) - 1;
1246        FlushBits(psBits, (leading_zeros << 1) + 1);
1247    }
1248    else
1249    {
1250        ReadBits(psBits, (leading_zeros << 1) + 1, &temp);
1251        *codeNum = temp - 1;
1252    }
1253
1254}
1255
1256
1257void se_v(mp4StreamType *psBits, int32 *value)
1258{
1259    int32 leadingZeros = 0;
1260    uint32 temp;
1261
1262    OSCL_UNUSED_ARG(value);
1263
1264    ReadBits(psBits, 1, &temp);
1265    while (!temp)
1266    {
1267        leadingZeros++;
1268        if (ReadBits(psBits, 1, &temp))
1269        {
1270            break;
1271        }
1272    }
1273    ReadBits(psBits, leadingZeros, &temp);
1274}
1275
1276void Parser_EBSPtoRBSP(uint8 *nal_unit, int32 *size)
1277{
1278    int32 i, j;
1279    int32 count = 0;
1280
1281
1282    for (i = 0; i < *size; i++)
1283    {
1284        if (count == 2 && nal_unit[i] == 0x03)
1285        {
1286            break;
1287        }
1288
1289        if (nal_unit[i])
1290            count = 0;
1291        else
1292            count++;
1293    }
1294
1295    count = 0;
1296    j = i++;
1297    for (;i < *size; i++)
1298    {
1299        if (count == 2 && nal_unit[i] == 0x03)
1300        {
1301            i++;
1302            count = 0;
1303        }
1304        nal_unit[j] = nal_unit[i];
1305        if (nal_unit[i])
1306            count = 0;
1307        else
1308            count++;
1309        j++;
1310    }
1311
1312    *size = j;
1313}
1314
1315
1316
1317